From 900ea0469f96e533e715ba9a340945c6aa8fcf3b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 6 Nov 2024 12:26:59 +0530 Subject: [PATCH] Ref --- .../photos/src/components/Sidebar/index.tsx | 6 ++-- .../photos/src/components/Upload/Uploader.tsx | 4 +-- .../photos/src/services/billingService.ts | 35 ++++++++++--------- web/apps/photos/src/utils/billing/index.ts | 10 ++++-- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index 425c7d291e..e43bec2bdc 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -63,7 +63,7 @@ import React, { useState, } from "react"; import { Trans } from "react-i18next"; -import billingService from "services/billingService"; +import { redirectToCustomerPortal } from "services/billingService"; import { getUncategorizedCollection } from "services/collectionService"; import exportService from "services/export"; import { getUserDetailsV2 } from "services/userService"; @@ -195,7 +195,7 @@ const UserDetailsSection: React.FC = ({ hasStripeSubscription(userDetails.subscription) && isSubscriptionPastDue(userDetails.subscription) ) { - billingService.redirectToCustomerPortal(); + redirectToCustomerPortal(); } else { galleryContext.showPlanSelectorModal(); } @@ -271,7 +271,7 @@ const SubscriptionStatus: React.FC = ({ hasStripeSubscription(userDetails.subscription) && isSubscriptionPastDue(userDetails.subscription) ) { - billingService.redirectToCustomerPortal(); + redirectToCustomerPortal(); } else { showPlanSelectorModal(); } diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index 163d72e6e8..99c1c6d59a 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -23,7 +23,7 @@ import { t } from "i18next"; import isElectron from "is-electron"; import { GalleryContext } from "pages/gallery"; import { useContext, useEffect, useRef, useState } from "react"; -import billingService from "services/billingService"; +import { redirectToCustomerPortal } from "services/billingService"; import { getLatestCollections } from "services/collectionService"; import { getPublicCollectionUID, @@ -659,7 +659,7 @@ export default function Uploader({ variant: "critical", subtext: t("subscription_expired"), message: t("renew_now"), - onClick: () => billingService.redirectToCustomerPortal(), + onClick: redirectToCustomerPortal, }; break; case CustomError.STORAGE_QUOTA_EXCEEDED: diff --git a/web/apps/photos/src/services/billingService.ts b/web/apps/photos/src/services/billingService.ts index eccaad7275..e84ff358e1 100644 --- a/web/apps/photos/src/services/billingService.ts +++ b/web/apps/photos/src/services/billingService.ts @@ -155,23 +155,6 @@ class billingService { throw e; } } - - public async redirectToCustomerPortal() { - try { - const redirectURL = completionRedirectURL(); - const response = await HTTPService.get( - await apiURL("/billing/stripe/customer-portal"), - { redirectURL }, - { - "X-Auth-Token": getToken(), - }, - ); - window.location.href = response.data.url; - } catch (e) { - log.error("unable to get customer portal url", e); - throw e; - } - } } export default new billingService(); @@ -214,3 +197,21 @@ const getPaymentToken = async () => { return z.object({ paymentToken: z.string() }).parse(await res.json()) .paymentToken; }; + +/** + * Redirect to the Stripe customer portal / dashboard where the user can view + * details about their subscription and modify their payment method. + */ +export const redirectToCustomerPortal = async () => { + const redirectURL = completionRedirectURL(); + const url = await apiURL("/billing/stripe/customer-portal"); + const params = new URLSearchParams({ redirectURL }); + const res = await fetch(`${url}?${params.toString()}`, { + headers: await authenticatedRequestHeaders(), + }); + ensureOk(res); + const data = z + .object({ data: z.object({ url: z.string() }) }) + .parse(await res.json()).data; + window.location.href = data.url; +}; diff --git a/web/apps/photos/src/utils/billing/index.ts b/web/apps/photos/src/utils/billing/index.ts index 5820c659de..fd316a058d 100644 --- a/web/apps/photos/src/utils/billing/index.ts +++ b/web/apps/photos/src/utils/billing/index.ts @@ -4,10 +4,14 @@ import { isPartOfFamily, } from "@/new/photos/services/user"; import { SetDialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; -import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; +import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; import { t } from "i18next"; import type { NextRouter } from "next/router"; -import billingService, { Plan, Subscription } from "services/billingService"; +import billingService, { + Plan, + redirectToCustomerPortal, + Subscription, +} from "services/billingService"; import { SetLoading } from "types/gallery"; import { BonusData, UserDetails } from "types/user"; import { getSubscriptionPurchaseSuccessMessage } from "utils/ui"; @@ -215,7 +219,7 @@ export async function updatePaymentMethod( ) { try { setLoading(true); - await billingService.redirectToCustomerPortal(); + await redirectToCustomerPortal(); } catch (error) { setLoading(false); setDialogMessage({