PAdd customer portal redirect, patch free trial endpoint

This commit is contained in:
Tuan Dang
2024-01-30 17:46:52 +07:00
parent 3cbda8e785
commit 40768631e0
4 changed files with 84 additions and 6 deletions
@@ -89,6 +89,26 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
} }
}); });
server.route({
url: "/:organizationId/customer-portal-session",
method: "POST",
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
200: z.any()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const data = await server.services.license.createOrganizationPortalSession({
actorId: req.permission.id,
actor: req.permission.type,
orgId: req.params.organizationId
});
return data;
}
});
server.route({ server.route({
url: "/:organizationId/plan/billing", url: "/:organizationId/plan/billing",
method: "GET", method: "GET",
@@ -24,7 +24,8 @@ import {
TOrgPlanDTO, TOrgPlanDTO,
TOrgPlansTableDTO, TOrgPlansTableDTO,
TOrgPmtMethodsDTO, TOrgPmtMethodsDTO,
TStartOrgTrailDTO, TStartOrgTrialDTO,
TCreateOrgPortalSession,
TUpdateOrgBillingDetailsDTO TUpdateOrgBillingDetailsDTO
} from "./license-types"; } from "./license-types";
@@ -201,7 +202,7 @@ export const licenseServiceFactory = ({
return plan; return plan;
}; };
const startOrgTrail = async ({ orgId, actorId, actor, success_url }: TStartOrgTrailDTO) => { const startOrgTrial = async ({ orgId, actorId, actor, success_url }: TStartOrgTrialDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create, OrgPermissionActions.Create,
@@ -222,13 +223,67 @@ export const licenseServiceFactory = ({
const { const {
data: { url } data: { url }
} = await licenseServerCloudApi.request.post( } = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/session/trail`, `/api/license-server/v1/customers/${organization.customerId}/session/trial`,
{ success_url } { success_url }
); );
featureStore.del(FEATURE_CACHE_KEY(orgId)); featureStore.del(FEATURE_CACHE_KEY(orgId));
return { url }; return { url };
}; };
const createOrganizationPortalSession = async ({ orgId, actorId, actor }: TCreateOrgPortalSession) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
throw new BadRequestError({
message: "Failed to find organization"
});
}
const {
data: { pmtMethods }
} = await licenseServerCloudApi.request.get(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`
);
if (pmtMethods.length < 1) {
// case: organization has no payment method on file
// -> redirect to add payment method portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`,
{
success_url: appCfg.SITE_URL + "/dashboard",
cancel_url: appCfg.SITE_URL + "/dashboard"
}
);
return { url };
} else {
// case: organization has payment method on file
// -> redirect to billing portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/billing-portal`,
{
return_url: appCfg.SITE_URL + "/dashboard"
}
);
return { url };
}
}
const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => { const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -511,7 +566,8 @@ export const licenseServiceFactory = ({
refreshPlan, refreshPlan,
getOrgPlan, getOrgPlan,
getOrgPlansTableByBillCycle, getOrgPlansTableByBillCycle,
startOrgTrail, startOrgTrial,
createOrganizationPortalSession,
getOrgBillingInfo, getOrgBillingInfo,
getOrgPlanTable, getOrgPlanTable,
getOrgBillingDetails, getOrgBillingDetails,
@@ -40,10 +40,12 @@ export type TOrgPlanDTO = {
projectId?: string; projectId?: string;
} & TOrgPermission; } & TOrgPermission;
export type TStartOrgTrailDTO = { export type TStartOrgTrialDTO = {
success_url: string; success_url: string;
} & TOrgPermission; } & TOrgPermission;
export type TCreateOrgPortalSession = TOrgPermission;
export type TGetOrgBillInfoDTO = TOrgPermission; export type TGetOrgBillInfoDTO = TOrgPermission;
export type TOrgPlanTableDTO = TOrgPermission; export type TOrgPlanTableDTO = TOrgPermission;
@@ -328,7 +328,7 @@ export const useCreateCustomerPortalSession = () => {
return useMutation({ return useMutation({
mutationFn: async (organizationId: string) => { mutationFn: async (organizationId: string) => {
const { data } = await apiRequest.post( const { data } = await apiRequest.post(
`/api/v1/organization/${organizationId}/customer-portal-session` `/api/v1/organizations/${organizationId}/customer-portal-session`
); );
return data; return data;
} }