perf: move stripe to billing service out of app store (#20376)
* add more methods to billingService * update profile handler * stripe customer handler * verify email * move imports + move generic methods to billing service * move to strip ebilling service class * push changes to mocks * fix enum * fix typo * correctly update customer metadata * fix userId type to number * fix types on billing services * fix type errors due to return methods differing * fix return types
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getStripeCustomerIdFromUserId } from "@calcom/app-store/stripepayment/lib/customer";
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getDubCustomer } from "@calcom/features/auth/lib/dub";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
@@ -8,7 +8,8 @@ import { DubReferralsPage } from "./DubReferralsPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Cal.com referral program - Earn money by sharing your link",
|
||||
description: "Earn 20% recurring commissions for a full year by referring others to Cal.com, while giving your referrals 20% off for 12 months. Share your link and start earning today!",
|
||||
description:
|
||||
"Earn 20% recurring commissions for a full year by referring others to Cal.com, while giving your referrals 20% off for 12 months. Share your link and start earning today!",
|
||||
};
|
||||
|
||||
// Export the appropriate component based on the feature flag
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { IS_STRIPE_ENABLED } from "@calcom/lib/constants";
|
||||
import { OrganizationRepository } from "@calcom/lib/server/repository/organization";
|
||||
@@ -43,6 +43,7 @@ export async function moveUserToMatchingOrg({ email }: { email: string }) {
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { token } = verifySchema.parse(req.query);
|
||||
const billingService = new StripeBillingService();
|
||||
|
||||
const foundToken = await prisma.verificationToken.findFirst({
|
||||
where: {
|
||||
@@ -130,7 +131,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
});
|
||||
|
||||
if (IS_STRIPE_ENABLED && userMetadataParsed.stripeCustomerId) {
|
||||
await stripe.customers.update(userMetadataParsed.stripeCustomerId, {
|
||||
await billingService.updateCustomer({
|
||||
customerId: userMetadataParsed.stripeCustomerId,
|
||||
email: updatedEmail,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { buffer } from "micro";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { HttpError as HttpCode } from "@calcom/lib/http-error";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
|
||||
|
||||
export async function getCustomerAndCheckoutSession(checkoutSessionId: string) {
|
||||
const checkoutSession = await stripe.checkout.sessions.retrieve(checkoutSessionId);
|
||||
const billingService = new StripeBillingService();
|
||||
const checkoutSession = await billingService.getCheckoutSession(checkoutSessionId);
|
||||
const customerOrCustomerId = checkoutSession.customer;
|
||||
let customerId = null;
|
||||
|
||||
@@ -16,7 +17,7 @@ export async function getCustomerAndCheckoutSession(checkoutSessionId: string) {
|
||||
} else {
|
||||
customerId = customerOrCustomerId.id;
|
||||
}
|
||||
const stripeCustomer = await stripe.customers.retrieve(customerId);
|
||||
const stripeCustomer = await billingService.getCustomer(customerId);
|
||||
if (stripeCustomer.deleted) {
|
||||
return { checkoutSession, stripeCustomer: null };
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { NextApiResponse } from "next";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
|
||||
import { sendEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
|
||||
import { createOrUpdateMemberships } from "@calcom/features/auth/signup/utils/createOrUpdateMemberships";
|
||||
import { prefillAvatar } from "@calcom/features/auth/signup/utils/prefillAvatar";
|
||||
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
|
||||
import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getLocaleFromRequest } from "@calcom/lib/getLocaleFromRequest";
|
||||
@@ -40,6 +40,8 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
})
|
||||
.parse(req.body);
|
||||
|
||||
const billingService = new StripeBillingService();
|
||||
|
||||
const shouldLockByDefault = await checkIfEmailIsBlockedInWatchlistController(_email);
|
||||
|
||||
log.debug("handler", { email: _email });
|
||||
@@ -96,7 +98,8 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
// Create the customer in Stripe
|
||||
const customer = await stripe.customers.create({
|
||||
|
||||
const customer = await billingService.createCustomer({
|
||||
email,
|
||||
metadata: {
|
||||
email /* Stripe customer email can be changed, so we add this to keep track of which email was used to signup */,
|
||||
@@ -108,22 +111,18 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
|
||||
// Pro username, must be purchased
|
||||
if (req.usernameStatus.statusCode === 402) {
|
||||
const checkoutSession = await stripe.checkout.sessions.create({
|
||||
const checkoutSession = await billingService.createSubscriptionCheckout({
|
||||
mode: "subscription",
|
||||
customer: customer.id,
|
||||
line_items: [
|
||||
{
|
||||
price: getPremiumMonthlyPlanPriceId(),
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
success_url: returnUrl,
|
||||
cancel_url: returnUrl,
|
||||
allow_promotion_codes: true,
|
||||
customerId: customer.stripeCustomerId,
|
||||
successUrl: returnUrl,
|
||||
cancelUrl: returnUrl,
|
||||
priceId: getPremiumMonthlyPlanPriceId(),
|
||||
quantity: 1,
|
||||
allowPromotionCodes: true,
|
||||
});
|
||||
|
||||
/** We create a username-less user until he pays */
|
||||
checkoutSessionId = checkoutSession.id;
|
||||
checkoutSessionId = checkoutSession.sessionId;
|
||||
username = null;
|
||||
}
|
||||
|
||||
@@ -168,7 +167,7 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
},
|
||||
});
|
||||
// Wrapping in a transaction as if one fails we want to rollback the whole thing to preventa any data inconsistencies
|
||||
const { membership } = await createOrUpdateMemberships({
|
||||
await createOrUpdateMemberships({
|
||||
user,
|
||||
team,
|
||||
});
|
||||
@@ -190,14 +189,14 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
});
|
||||
} else {
|
||||
// Create the user
|
||||
const user = await prisma.user.create({
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
email,
|
||||
locked: shouldLockByDefault,
|
||||
password: { create: { hash: hashedPassword } },
|
||||
metadata: {
|
||||
stripeCustomerId: customer.id,
|
||||
stripeCustomerId: customer.stripeCustomerId,
|
||||
checkoutSessionId,
|
||||
},
|
||||
creationSource: CreationSource.WEBAPP,
|
||||
@@ -221,7 +220,7 @@ async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(201).json({ message: "Created user", stripeCustomerId: customer.id });
|
||||
return res.status(201).json({ message: "Created user", stripeCustomerId: customer.stripeCustomerId });
|
||||
}
|
||||
|
||||
export default usernameHandler(handler);
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
|
||||
import { stripeWebhookHandler, HttpCode } from "./__handler";
|
||||
|
||||
@@ -11,7 +11,7 @@ vi.mock("micro", () => ({
|
||||
buffer: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@calcom/app-store/stripepayment/lib/server", () => ({
|
||||
vi.mock("@calcom/features/ee/payments/server/stripe", () => ({
|
||||
default: {
|
||||
webhooks: {
|
||||
constructEvent: vi.fn(),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { buffer } from "micro";
|
||||
import type { NextApiRequest } from "next";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
/** Stripe Webhook Handler Mappings */
|
||||
|
||||
@@ -31,6 +31,19 @@ export interface BillingService {
|
||||
metadata?: Record<string, string | number>;
|
||||
mode?: "subscription" | "setup" | "payment";
|
||||
allowPromotionCodes?: boolean;
|
||||
customerUpdate?: {
|
||||
address?: "auto" | "never";
|
||||
};
|
||||
automaticTax?: {
|
||||
enabled: boolean;
|
||||
};
|
||||
discounts?: Array<{
|
||||
coupon: string;
|
||||
}>;
|
||||
subscriptionData?: {
|
||||
metadata?: Record<string, string | number>;
|
||||
trial_period_days?: number;
|
||||
};
|
||||
}): Promise<{ checkoutUrl: string | null; sessionId: string }>;
|
||||
|
||||
// Price management
|
||||
@@ -42,5 +55,11 @@ export interface BillingService {
|
||||
productId: string;
|
||||
metadata?: Record<string, string | number>;
|
||||
}): Promise<{ priceId: string }>;
|
||||
getPrice(priceId: string): Promise<Stripe.Price | null>;
|
||||
getSubscriptionStatus(subscriptionId: string): Promise<Stripe.Subscription.Status | null>;
|
||||
|
||||
getCheckoutSession(checkoutSessionId: string): Promise<Stripe.Checkout.Session | null>;
|
||||
getCustomer(customerId: string): Promise<Stripe.Customer | Stripe.DeletedCustomer | null>;
|
||||
getSubscriptions(customerId: string): Promise<Stripe.Subscription[] | null>;
|
||||
updateCustomer(args: { customerId: string; email: string; userId?: number }): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ export class StripeBillingService implements BillingService {
|
||||
metadata,
|
||||
mode = "subscription",
|
||||
allowPromotionCodes = true,
|
||||
customerUpdate,
|
||||
automaticTax,
|
||||
discounts,
|
||||
subscriptionData,
|
||||
} = args;
|
||||
|
||||
const session = await this.stripe.checkout.sessions.create({
|
||||
@@ -65,6 +69,10 @@ export class StripeBillingService implements BillingService {
|
||||
},
|
||||
],
|
||||
allow_promotion_codes: allowPromotionCodes,
|
||||
customer_update: customerUpdate,
|
||||
automatic_tax: automaticTax,
|
||||
discounts,
|
||||
subscription_data: subscriptionData,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -122,4 +130,32 @@ export class StripeBillingService implements BillingService {
|
||||
|
||||
return subscription.status;
|
||||
}
|
||||
|
||||
async getCheckoutSession(checkoutSessionId: string) {
|
||||
const checkoutSession = await this.stripe.checkout.sessions.retrieve(checkoutSessionId);
|
||||
return checkoutSession;
|
||||
}
|
||||
|
||||
async getCustomer(customerId: string) {
|
||||
const customer = await this.stripe.customers.retrieve(customerId);
|
||||
return customer;
|
||||
}
|
||||
|
||||
async getSubscriptions(customerId: string) {
|
||||
const subscriptions = await this.stripe.subscriptions.list({ customer: customerId });
|
||||
return subscriptions.data;
|
||||
}
|
||||
|
||||
async updateCustomer(args: Parameters<BillingService["updateCustomer"]>[0]) {
|
||||
const { customerId, email, userId } = args;
|
||||
const metadata: { email?: string; userId?: number } = {};
|
||||
if (email) metadata.email = email;
|
||||
if (userId) metadata.userId = userId;
|
||||
await this.stripe.customers.update(customerId, { metadata });
|
||||
}
|
||||
|
||||
async getPrice(priceId: string) {
|
||||
const price = await this.stripe.prices.retrieve(priceId);
|
||||
return price;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ import { buffer } from "micro";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import type Stripe from "stripe";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { sendAttendeeRequestEmailAndSMS, sendOrganizerRequestEmail } from "@calcom/emails";
|
||||
import { doesBookingRequireConfirmation } from "@calcom/features/bookings/lib/doesBookingRequireConfirmation";
|
||||
import { getAllCredentials } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
|
||||
@@ -2,7 +2,8 @@ import prismock from "../../../../../tests/libs/__mocks__/prisma";
|
||||
|
||||
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { BillingPeriod } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import {
|
||||
getTeamWithPaymentMetadata,
|
||||
@@ -41,7 +42,7 @@ vi.mock("@calcom/lib/constant", () => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("@calcom/app-store/stripepayment/lib/server", () => {
|
||||
vi.mock("@calcom/features/ee/payments/server/stripe", () => {
|
||||
return {
|
||||
default: {
|
||||
checkout: {
|
||||
@@ -182,7 +183,7 @@ describe("purchaseTeamOrOrgSubscription", () => {
|
||||
userId: user.id,
|
||||
isOrg: true,
|
||||
pricePerSeat: 100,
|
||||
billingPeriod: "MONTHLY",
|
||||
billingPeriod: BillingPeriod.MONTHLY,
|
||||
})
|
||||
).toEqual({ url: "SESSION_URL" });
|
||||
|
||||
@@ -253,7 +254,7 @@ describe("purchaseTeamOrOrgSubscription", () => {
|
||||
userId: user.id,
|
||||
isOrg: true,
|
||||
pricePerSeat: 100,
|
||||
billingPeriod: "ANNUALLY",
|
||||
billingPeriod: BillingPeriod.ANNUALLY,
|
||||
})
|
||||
).toEqual({ url: "SESSION_URL" });
|
||||
|
||||
@@ -324,7 +325,8 @@ describe("purchaseTeamOrOrgSubscription", () => {
|
||||
seatsToChargeFor,
|
||||
userId: user.id,
|
||||
isOrg: true,
|
||||
billingPeriod: "ANNUALLY",
|
||||
billingPeriod: BillingPeriod.ANNUALLY,
|
||||
pricePerSeat: null,
|
||||
})
|
||||
).toEqual({ url: "SESSION_URL" });
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import type Stripe from "stripe";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getStripeCustomerIdFromUserId } from "@calcom/app-store/stripepayment/lib/customer";
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getDubCustomer } from "@calcom/features/auth/lib/dub";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import {
|
||||
IS_PRODUCTION,
|
||||
MINIMUM_NUMBER_OF_ORG_SEATS,
|
||||
|
||||
@@ -9,12 +9,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { WorkingHours } from "@calcom/types/schedule";
|
||||
import cs from "@calcom/ui/classNames";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTrigger,
|
||||
DialogClose,
|
||||
} from "@calcom/ui/components/dialog";
|
||||
import { DialogContent, DialogHeader, DialogTrigger, DialogClose } from "@calcom/ui/components/dialog";
|
||||
import { Switch } from "@calcom/ui/components/form";
|
||||
import { Form } from "@calcom/ui/components/form";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import {
|
||||
ZStripeCheckoutSessionInputSchema,
|
||||
type TStripeCheckoutSessionInputSchema,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { userMetadata } from "@calcom/prisma/zod-utils";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
||||
@@ -16,11 +16,14 @@ export const stripeCustomerHandler = async ({ ctx }: StripeCustomerOptions) => {
|
||||
user: { id: userId },
|
||||
} = ctx;
|
||||
|
||||
const billingService = new StripeBillingService();
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
select: {
|
||||
email: true,
|
||||
metadata: true,
|
||||
},
|
||||
});
|
||||
@@ -33,7 +36,8 @@ export const stripeCustomerHandler = async ({ ctx }: StripeCustomerOptions) => {
|
||||
let stripeCustomerId = metadata?.stripeCustomerId;
|
||||
if (!stripeCustomerId) {
|
||||
// Create stripe customer
|
||||
const customer = await stripe.customers.create({
|
||||
const customer = await billingService.createCustomer({
|
||||
email: user.email,
|
||||
metadata: {
|
||||
userId: userId.toString(),
|
||||
},
|
||||
@@ -45,15 +49,15 @@ export const stripeCustomerHandler = async ({ ctx }: StripeCustomerOptions) => {
|
||||
data: {
|
||||
metadata: {
|
||||
...metadata,
|
||||
stripeCustomerId: customer.id,
|
||||
stripeCustomerId: customer.stripeCustomerId,
|
||||
},
|
||||
},
|
||||
});
|
||||
stripeCustomerId = customer.id;
|
||||
stripeCustomerId = customer.stripeCustomerId;
|
||||
}
|
||||
|
||||
// Fetch stripe customer
|
||||
const customer = await stripe.customers.retrieve(stripeCustomerId);
|
||||
const customer = await billingService.getCustomer(stripeCustomerId);
|
||||
if (customer.deleted) {
|
||||
throw new TRPCError({ code: "BAD_REQUEST", message: "No stripe customer found" });
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Prisma } from "@prisma/client";
|
||||
import { keyBy } from "lodash";
|
||||
import type { GetServerSidePropsContext, NextApiResponse } from "next";
|
||||
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { sendChangeOfEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
|
||||
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
|
||||
import { getFeatureFlag } from "@calcom/features/flags/server/utils";
|
||||
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
@@ -37,6 +37,7 @@ type UpdateProfileOptions = {
|
||||
|
||||
export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) => {
|
||||
const { user } = ctx;
|
||||
const billingService = new StripeBillingService();
|
||||
const userMetadata = handleUserMetadata({ ctx, input });
|
||||
const locale = input.locale || user.locale;
|
||||
const emailVerification = await getFeatureFlag(prisma, "email-verification");
|
||||
@@ -84,9 +85,9 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions)
|
||||
throw new TRPCError({ code: "BAD_REQUEST", message: "User is not premium" });
|
||||
}
|
||||
|
||||
const stripeSubscriptions = await stripe.subscriptions.list({ customer: stripeCustomerId });
|
||||
const stripeSubscriptions = await billingService.getSubscriptions(stripeCustomerId);
|
||||
|
||||
if (!stripeSubscriptions || !stripeSubscriptions.data.length) {
|
||||
if (!stripeSubscriptions || !stripeSubscriptions.length) {
|
||||
throw new TRPCError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: "No stripeSubscription found",
|
||||
@@ -95,7 +96,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions)
|
||||
|
||||
// Iterate over subscriptions and look for premium product id and status active
|
||||
// @TODO: iterate if stripeSubscriptions.hasMore is true
|
||||
const isPremiumUsernameSubscriptionActive = stripeSubscriptions.data.some(
|
||||
const isPremiumUsernameSubscriptionActive = stripeSubscriptions.some(
|
||||
(subscription) =>
|
||||
subscription.items.data[0].price.id === getPremiumMonthlyPlanPriceId() &&
|
||||
subscription.status === "active"
|
||||
@@ -284,12 +285,10 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions)
|
||||
// Notify stripe about the change
|
||||
if (updatedUser && updatedUser.metadata && hasKeyInMetadata(updatedUser, "stripeCustomerId")) {
|
||||
const stripeCustomerId = `${updatedUser.metadata.stripeCustomerId}`;
|
||||
await stripe.customers.update(stripeCustomerId, {
|
||||
metadata: {
|
||||
username: updatedUser.username,
|
||||
email: updatedUser.email,
|
||||
userId: updatedUser.id,
|
||||
},
|
||||
await billingService.updateCustomer({
|
||||
customerId: stripeCustomerId,
|
||||
email: updatedUser.email,
|
||||
userId: updatedUser.id,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user