change plan
parent
d7390e7024
commit
a41a0923da
|
@ -28,7 +28,7 @@
|
||||||
"pino-pretty": "^10.3.1",
|
"pino-pretty": "^10.3.1",
|
||||||
"react-microsoft-clarity": "^1.2.0",
|
"react-microsoft-clarity": "^1.2.0",
|
||||||
"sequelize": "^6.35.2",
|
"sequelize": "^6.35.2",
|
||||||
"stripe": "^14.16.0",
|
"stripe": "^14.23.0",
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
"swagger-ui-express": "^5.0.0",
|
"swagger-ui-express": "^5.0.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
|
@ -2786,9 +2786,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stripe": {
|
"node_modules/stripe": {
|
||||||
"version": "14.16.0",
|
"version": "14.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/stripe/-/stripe-14.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/stripe/-/stripe-14.23.0.tgz",
|
||||||
"integrity": "sha512-1gOr2LzafWV84cPIO5Md/QPh4XVPLKULVuRpBVOV3Plq3seiHmg/eeOktX+hDl8jpNZuORHYaUJGrNqrABLwdg==",
|
"integrity": "sha512-OPD7LqBmni6uDdqA05GGgMZyyRWxJOehONBNC9tYgY4Uh089EtXd6QLIgRGrqTDlQH3cA2BXo848nxwa/zsQzw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": ">=8.1.0",
|
"@types/node": ">=8.1.0",
|
||||||
"qs": "^6.11.0"
|
"qs": "^6.11.0"
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
"pino-pretty": "^10.3.1",
|
"pino-pretty": "^10.3.1",
|
||||||
"react-microsoft-clarity": "^1.2.0",
|
"react-microsoft-clarity": "^1.2.0",
|
||||||
"sequelize": "^6.35.2",
|
"sequelize": "^6.35.2",
|
||||||
"stripe": "^14.16.0",
|
"stripe": "^14.23.0",
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
"swagger-ui-express": "^5.0.0",
|
"swagger-ui-express": "^5.0.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
|
|
|
@ -6,11 +6,9 @@ import {
|
||||||
PAYMENT_PLAN,
|
PAYMENT_PLAN,
|
||||||
PAYMENT_PLAN_SETTINGS,
|
PAYMENT_PLAN_SETTINGS,
|
||||||
} from "../utils/constants";
|
} from "../utils/constants";
|
||||||
import UserPendingPayment from "../models/userPendingPayment";
|
|
||||||
import User from "../models/user";
|
import User from "../models/user";
|
||||||
import { getUserSession, stripe } from "../utils/utils";
|
import { getUserSession, stripe } from "../utils/utils";
|
||||||
import Store from "../models/store";
|
import { telegramNotification } from "../utils/adminDashboard";
|
||||||
import Session from "../models/session";
|
|
||||||
|
|
||||||
const ZeitAdlerBasicMonthly = "za-basic-monthly";
|
const ZeitAdlerBasicMonthly = "za-basic-monthly";
|
||||||
const ZeitAdlerBasicYearly = "za-basic-yearly";
|
const ZeitAdlerBasicYearly = "za-basic-yearly";
|
||||||
|
@ -198,17 +196,57 @@ export async function CreateCheckoutSession(req: Request, res: Response) {
|
||||||
subscriptions.data.length > 0 &&
|
subscriptions.data.length > 0 &&
|
||||||
subscriptions.data[0].id !== priceId
|
subscriptions.data[0].id !== priceId
|
||||||
) {
|
) {
|
||||||
const latestSubscription = subscriptions.data[0];
|
const currentSubscription = subscriptions.data[0];
|
||||||
|
const currentItem = currentSubscription.items.data[0];
|
||||||
|
|
||||||
await stripe.subscriptions.update(latestSubscription.id, {
|
// Calculate the prorated credit for the old subscription
|
||||||
|
const endCurrentSub = currentSubscription.current_period_end;
|
||||||
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
let proratedCredit = 0;
|
||||||
|
if (currentItem.price.unit_amount !== null) {
|
||||||
|
proratedCredit = Math.round(
|
||||||
|
((endCurrentSub - now) /
|
||||||
|
(endCurrentSub - currentSubscription.current_period_start)) *
|
||||||
|
currentItem.price.unit_amount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an invoice item for the prorated credit
|
||||||
|
/*await stripe.invoiceItems.create({
|
||||||
|
customer: user.stripe_customer_id,
|
||||||
|
amount: -proratedCredit,
|
||||||
|
currency: currentItem.price.currency,
|
||||||
|
description: "Prorated credit for plan switch",
|
||||||
|
}); */
|
||||||
|
|
||||||
|
const updatedSubscription = await stripe.subscriptions.update(
|
||||||
|
currentSubscription.id,
|
||||||
|
{
|
||||||
|
cancel_at_period_end: false,
|
||||||
|
proration_behavior: "always_invoice",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: latestSubscription.items.data[0].id,
|
id: currentSubscription.items.data[0].id,
|
||||||
price: priceId,
|
price: priceId,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Attempt to pay any open invoices immediately, ensuring the customer pays for the new plan right away
|
||||||
|
const invoice = await stripe.invoices.create({
|
||||||
|
customer: user.stripe_customer_id,
|
||||||
|
subscription: updatedSubscription.id,
|
||||||
|
auto_advance: true, // Automatically pay the invoice if the customer has a default payment method
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Finalize the invoice immediately to collect payment
|
||||||
|
if (invoice.status !== "paid") {
|
||||||
|
await stripe.invoices.finalizeInvoice(invoice.id, {
|
||||||
|
auto_advance: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// update user
|
// update user
|
||||||
|
|
||||||
await User.update(
|
await User.update(
|
||||||
|
@ -224,7 +262,12 @@ export async function CreateCheckoutSession(req: Request, res: Response) {
|
||||||
|
|
||||||
userLogger.info(
|
userLogger.info(
|
||||||
userSession.user_id,
|
userSession.user_id,
|
||||||
`CreateCheckoutSession: update subscription ${latestSubscription.id} to ${priceId}`
|
`CreateCheckoutSession: update subscription ${currentSubscription.id} to ${priceId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
telegramNotification(
|
||||||
|
1,
|
||||||
|
`User ${userSession.user_id} updated subscription ${currentSubscription.id} to ${priceId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(200).json({ status: "ok" });
|
return res.status(200).json({ status: "ok" });
|
||||||
|
@ -233,7 +276,7 @@ export async function CreateCheckoutSession(req: Request, res: Response) {
|
||||||
|
|
||||||
// create checkout session
|
// create checkout session
|
||||||
|
|
||||||
const session = await stripe.checkout.sessions.create({
|
let sessionData = {
|
||||||
payment_method_types: ["card"],
|
payment_method_types: ["card"],
|
||||||
line_items: [
|
line_items: [
|
||||||
{
|
{
|
||||||
|
@ -243,20 +286,33 @@ export async function CreateCheckoutSession(req: Request, res: Response) {
|
||||||
],
|
],
|
||||||
billing_address_collection: "required",
|
billing_address_collection: "required",
|
||||||
mode: "subscription",
|
mode: "subscription",
|
||||||
subscription_data: {
|
|
||||||
trial_end: new Date(user.payment_plan_trial_end).getTime() / 1000,
|
|
||||||
},
|
|
||||||
success_url: `${DASHBOARD_URL}/payment-plan`,
|
success_url: `${DASHBOARD_URL}/payment-plan`,
|
||||||
cancel_url: `${DASHBOARD_URL}/payment-plan`,
|
cancel_url: `${DASHBOARD_URL}/payment-plan`,
|
||||||
metadata: {
|
metadata: {
|
||||||
userId: userSession.user_id,
|
userId: userSession.user_id,
|
||||||
payment_plan_interval: lookupKey === ZeitAdlerBasicYearly ? 1 : 0,
|
payment_plan_interval: lookupKey === ZeitAdlerBasicYearly ? 1 : 0,
|
||||||
} /*
|
},
|
||||||
|
/*
|
||||||
automatic_tax: {
|
automatic_tax: {
|
||||||
// see https://dashboard.stripe.com/settings/tax
|
// see https://dashboard.stripe.com/settings/tax
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},*/,
|
},*/
|
||||||
});
|
} as any;
|
||||||
|
|
||||||
|
if (
|
||||||
|
user.payment_plan_trial_end !== null &&
|
||||||
|
new Date(user.payment_plan_trial_end) > new Date()
|
||||||
|
) {
|
||||||
|
sessionData = {
|
||||||
|
...sessionData,
|
||||||
|
subscription_data: {
|
||||||
|
trial_end: new Date(user.payment_plan_trial_end).getTime() / 1000,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await stripe.checkout.sessions.create(sessionData);
|
||||||
/*
|
/*
|
||||||
await UserPendingPayment.create({
|
await UserPendingPayment.create({
|
||||||
payment_session_id: session.id,
|
payment_session_id: session.id,
|
||||||
|
@ -280,7 +336,7 @@ export async function CreateCheckoutSession(req: Request, res: Response) {
|
||||||
|
|
||||||
// user is redirected to dashboard checkout page after successful payment
|
// user is redirected to dashboard checkout page after successful payment
|
||||||
// and then makes request to this endpoint to create a user session
|
// and then makes request to this endpoint to create a user session
|
||||||
export async function CheckoutSuccess(req: Request, res: Response) {
|
/*export async function CheckoutSuccess(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { sessionId } = req.body;
|
const { sessionId } = req.body;
|
||||||
|
|
||||||
|
@ -365,7 +421,7 @@ export async function CheckoutCanceled(req: Request, res: Response) {
|
||||||
logger.error("CheckoutCanceled", error as string);
|
logger.error("CheckoutCanceled", error as string);
|
||||||
res.status(500).send({ err: "invalid request" });
|
res.status(500).send({ err: "invalid request" });
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
export async function StripeWebhook(req: Request, res: Response) {
|
export async function StripeWebhook(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
|
@ -449,6 +505,11 @@ export async function StripeWebhook(req: Request, res: Response) {
|
||||||
event.data.object
|
event.data.object
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
telegramNotification(
|
||||||
|
1,
|
||||||
|
`User ${userId} completed checkout session ${session.id}`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
`StripeWebhook: checkout.session.completed: user not found for userId: ${userId}`
|
`StripeWebhook: checkout.session.completed: user not found for userId: ${userId}`
|
||||||
|
@ -511,6 +572,10 @@ export async function StripeWebhook(req: Request, res: Response) {
|
||||||
payment_plan_status: status,
|
payment_plan_status: status,
|
||||||
/*payment_plan_trial_end:
|
/*payment_plan_trial_end:
|
||||||
trialEnd !== null ? new Date(trialEnd * 1000) : null, */
|
trialEnd !== null ? new Date(trialEnd * 1000) : null, */
|
||||||
|
payment_plan_cancel_at:
|
||||||
|
subscription.cancel_at !== null
|
||||||
|
? new Date(subscription.cancel_at * 1000)
|
||||||
|
: null, // this is if the user cancels the subscription after the trial period
|
||||||
payment_plan_canceled_at:
|
payment_plan_canceled_at:
|
||||||
canceledAt !== null ? new Date(canceledAt * 1000) : null,
|
canceledAt !== null ? new Date(canceledAt * 1000) : null,
|
||||||
};
|
};
|
||||||
|
@ -528,57 +593,13 @@ export async function StripeWebhook(req: Request, res: Response) {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn(`StripeWebhook: Ignoring unknown event: ${event.type}`);
|
logger.warn(
|
||||||
|
`StripeWebhook: Ignoring unknown event: ${
|
||||||
|
event.type
|
||||||
|
} data: ${JSON.stringify(event.data)}`
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (event.type === "checkout.session.completed") {
|
|
||||||
const userId = (event.data.object as Stripe.Checkout.Session)?.metadata
|
|
||||||
?.userId;
|
|
||||||
|
|
||||||
// delete user pending payment
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
"delete user pending payment",
|
|
||||||
(event.data.object as Stripe.Checkout.Session).id
|
|
||||||
);
|
|
||||||
|
|
||||||
const pendingPayment = await UserPendingPayment.findOne({
|
|
||||||
where: {
|
|
||||||
payment_session_id: (event.data.object as Stripe.Checkout.Session).id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pendingPayment !== null) {
|
|
||||||
await pendingPayment.destroy();
|
|
||||||
|
|
||||||
const user = await User.findOne({
|
|
||||||
where: {
|
|
||||||
user_id: userId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (user !== null && user.state === ACCOUNT_STATE.INIT_PAYMENT) {
|
|
||||||
// update user state
|
|
||||||
await User.update(
|
|
||||||
{
|
|
||||||
state: ACCOUNT_STATE.ACTIVE,
|
|
||||||
stripe_customer_id: (event.data.object as Stripe.Checkout.Session)
|
|
||||||
.customer as string,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
where: {
|
|
||||||
user_id: userId,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (event.type === "checkout.session.expired") {
|
|
||||||
logger.info(`webhook checkout.session.expired: ${event.data.object.id}`);
|
|
||||||
} else {
|
|
||||||
logger.warn(`Ignoring unknown event: ${event.type}`);
|
|
||||||
} */
|
|
||||||
|
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -599,7 +620,11 @@ export async function GetBillingPortal(req: Request, res: Response) {
|
||||||
where: {
|
where: {
|
||||||
user_id: userSession.user_id,
|
user_id: userSession.user_id,
|
||||||
},
|
},
|
||||||
attributes: ["stripe_customer_id"],
|
attributes: [
|
||||||
|
"payment_plan",
|
||||||
|
"payment_plan_interval",
|
||||||
|
"stripe_customer_id",
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user === null || user.stripe_customer_id === null) {
|
if (user === null || user.stripe_customer_id === null) {
|
||||||
|
@ -611,6 +636,74 @@ export async function GetBillingPortal(req: Request, res: Response) {
|
||||||
return res.status(400).send({ err: "invalid request" });
|
return res.status(400).send({ err: "invalid request" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// after the trial period, the subscribtion is deleted
|
||||||
|
// so we need to check if the user has a subscription or not
|
||||||
|
|
||||||
|
const subscriptions = await stripe.subscriptions.list({
|
||||||
|
customer: user.stripe_customer_id,
|
||||||
|
limit: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("subs", subscriptions.data.length, user.payment_plan);
|
||||||
|
|
||||||
|
if (subscriptions.data.length === 0) {
|
||||||
|
let lookupKey = [ZeitAdlerBasicMonthly, ZeitAdlerBasicYearly];
|
||||||
|
|
||||||
|
console.log("user", user.payment_plan_interval);
|
||||||
|
|
||||||
|
await loadPrices();
|
||||||
|
|
||||||
|
let priceId = cachedPrices.find(
|
||||||
|
(price) => price.lookup_key === lookupKey[user.payment_plan_interval]
|
||||||
|
)?.id;
|
||||||
|
|
||||||
|
if (priceId === undefined) {
|
||||||
|
return res.status(400).send({ err: "invalid request" });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"priceId",
|
||||||
|
priceId,
|
||||||
|
user.payment_plan_interval,
|
||||||
|
user.payment_plan_trial_end
|
||||||
|
);
|
||||||
|
|
||||||
|
const session = await stripe.checkout.sessions.create({
|
||||||
|
payment_method_types: ["card"],
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
price: priceId,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
billing_address_collection: "required",
|
||||||
|
mode: "subscription",
|
||||||
|
/*subscription_data: {
|
||||||
|
trial_end: new Date(user.payment_plan_trial_end).getTime() / 1000,
|
||||||
|
},*/
|
||||||
|
success_url: `${DASHBOARD_URL}/payment-plan`,
|
||||||
|
cancel_url: `${DASHBOARD_URL}/payment-plan`,
|
||||||
|
metadata: {
|
||||||
|
userId: userSession.user_id,
|
||||||
|
payment_plan_interval: user.payment_plan_interval,
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
automatic_tax: {
|
||||||
|
// see https://dashboard.stripe.com/settings/tax
|
||||||
|
enabled: true,
|
||||||
|
},*/
|
||||||
|
});
|
||||||
|
|
||||||
|
userLogger.info(
|
||||||
|
userSession.user_id,
|
||||||
|
`GetBillingPortal: create checkout session ${session.id}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
url: session.url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const session = await stripe.billingPortal.sessions.create({
|
const session = await stripe.billingPortal.sessions.create({
|
||||||
customer: user.stripe_customer_id,
|
customer: user.stripe_customer_id,
|
||||||
return_url: `${DASHBOARD_URL}/payment-plan`,
|
return_url: `${DASHBOARD_URL}/payment-plan`,
|
||||||
|
|
|
@ -474,6 +474,7 @@ export async function GetUser(req: Request, res: Response) {
|
||||||
"analytics_enabled",
|
"analytics_enabled",
|
||||||
"payment_plan",
|
"payment_plan",
|
||||||
"payment_plan_trial_end",
|
"payment_plan_trial_end",
|
||||||
|
"payment_plan_cancel_at",
|
||||||
"payment_plan_canceled_at",
|
"payment_plan_canceled_at",
|
||||||
"created_at",
|
"created_at",
|
||||||
],
|
],
|
||||||
|
@ -517,8 +518,12 @@ export async function GetUser(req: Request, res: Response) {
|
||||||
user.payment_plan === PAYMENT_PLAN.TRAILING ||
|
user.payment_plan === PAYMENT_PLAN.TRAILING ||
|
||||||
user.payment_plan_canceled_at !== null
|
user.payment_plan_canceled_at !== null
|
||||||
) {
|
) {
|
||||||
|
if (user.payment_plan_cancel_at !== null) {
|
||||||
|
respData.user["payment_plan_trial_end"] = user.payment_plan_cancel_at;
|
||||||
|
} else {
|
||||||
respData.user["payment_plan_trial_end"] = user.payment_plan_trial_end;
|
respData.user["payment_plan_trial_end"] = user.payment_plan_trial_end;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if user is not a store master, then check if user is a worker
|
// if user is not a store master, then check if user is a worker
|
||||||
if (!stores || stores.length === 0) {
|
if (!stores || stores.length === 0) {
|
||||||
|
@ -557,6 +562,8 @@ export async function GetUser(req: Request, res: Response) {
|
||||||
user.payment_plan
|
user.payment_plan
|
||||||
}. Possible highest payment plan is ${PAYMENT_PLAN_SETTINGS.length - 1}`
|
}. Possible highest payment plan is ${PAYMENT_PLAN_SETTINGS.length - 1}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return res.status(400).send({ err: "invalid request" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// update user session last_used
|
// update user session last_used
|
||||||
|
|
|
@ -17,10 +17,11 @@ interface UserAttributes {
|
||||||
google_account_name?: string;
|
google_account_name?: string;
|
||||||
google_account_picture?: string;
|
google_account_picture?: string;
|
||||||
analytics_enabled: boolean;
|
analytics_enabled: boolean;
|
||||||
payment_plan: number;
|
payment_plan: number; // 0 trailing, 1 basic
|
||||||
payment_plan_interval?: number;
|
payment_plan_interval?: number; // how often the payment plan is charged (e.g. 0 monthly, 1 yearly)
|
||||||
payment_plan_trial_end?: Date;
|
payment_plan_trial_end?: Date; // when the payment plan trial ends
|
||||||
payment_plan_canceled_at?: Date;
|
payment_plan_cancel_at?: Date; // when the payment plan will be canceled (e.g. after trial)
|
||||||
|
payment_plan_canceled_at?: Date; // when the payment plan was canceled
|
||||||
stripe_customer_id?: string;
|
stripe_customer_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ class User extends Model<UserAttributes> implements UserAttributes {
|
||||||
declare payment_plan: number;
|
declare payment_plan: number;
|
||||||
declare payment_plan_interval: number;
|
declare payment_plan_interval: number;
|
||||||
declare payment_plan_trial_end: Date;
|
declare payment_plan_trial_end: Date;
|
||||||
|
declare payment_plan_cancel_at: Date;
|
||||||
declare payment_plan_canceled_at: Date;
|
declare payment_plan_canceled_at: Date;
|
||||||
declare stripe_customer_id: string;
|
declare stripe_customer_id: string;
|
||||||
declare created_at: Date;
|
declare created_at: Date;
|
||||||
|
@ -119,6 +121,10 @@ User.init(
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
},
|
},
|
||||||
|
payment_plan_cancel_at: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
payment_plan_canceled_at: {
|
payment_plan_canceled_at: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
|
|
|
@ -10,8 +10,8 @@ router.get("/prices/:productId", paymentController.GetPrices);
|
||||||
// webhook is registered in server.ts as it needs registered before the body parser
|
// webhook is registered in server.ts as it needs registered before the body parser
|
||||||
|
|
||||||
router.post("/checkout", paymentController.CreateCheckoutSession);
|
router.post("/checkout", paymentController.CreateCheckoutSession);
|
||||||
router.post("/checkout/success", paymentController.CheckoutSuccess);
|
// router.post("/checkout/success", paymentController.CheckoutSuccess);
|
||||||
router.post("/checkout/canceled", paymentController.CheckoutCanceled);
|
// router.post("/checkout/canceled", paymentController.CheckoutCanceled);
|
||||||
router.get("/portal", paymentController.GetBillingPortal);
|
router.get("/portal", paymentController.GetBillingPortal);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -183,7 +183,9 @@ export function isCalendarMinEarliestBookingTimeValid(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPaymentPlanValid(paymentPlan: number) {
|
export function isPaymentPlanValid(paymentPlan: number) {
|
||||||
return paymentPlan >= PAYMENT_PLAN.BASIC && paymentPlan <= PAYMENT_PLAN.BASIC;
|
return (
|
||||||
|
paymentPlan >= PAYMENT_PLAN.TRAILING && paymentPlan <= PAYMENT_PLAN.BASIC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCompanyNameValid(companyName: string) {
|
export function isCompanyNameValid(companyName: string) {
|
||||||
|
|
Loading…
Reference in New Issue