105 lines
4.4 KiB
TypeScript
105 lines
4.4 KiB
TypeScript
import { BackendVariables } from "@Common/config/variables/Variables";
|
|
import ApiController from "@Common/system/controller-pattern/ApiController";
|
|
import { Controller, Post } from "@ControllerPattern/index";
|
|
import SubscriptionsService from "@Services/admin/SubscriptionsService/SubscriptionsService.ts";
|
|
import StripeService from "@Services/common/StripeService/StripeService";
|
|
import { validateOrReject } from "class-validator";
|
|
import { Request, Response } from "express";
|
|
import { Subscription } from "le-coffre-resources/dist/Admin";
|
|
import { Service } from "typedi";
|
|
|
|
@Controller()
|
|
@Service()
|
|
export default class StripeWebhooks extends ApiController {
|
|
constructor(private stripeService: StripeService, private subscriptionsService: SubscriptionsService, private backendVariables: BackendVariables) {
|
|
super();
|
|
}
|
|
|
|
/**
|
|
* @description Create a new checkout session
|
|
*/
|
|
@Post("/api/v1/webhooks/stripe")
|
|
protected async post(req: Request, response: Response) {
|
|
try {
|
|
const event = req.body;
|
|
|
|
switch (event.type) {
|
|
//Manage plan switch + recurring payment
|
|
case "invoice.payment_succeeded":
|
|
if (event.data.object.billing_reason !== "subscription_update" && event.data.object.billing_reason !== "subscription_cycle") break;
|
|
const stripeSubscription = await this.stripeService.getClient().subscriptions.retrieve(event.data.object.subscription);
|
|
if(stripeSubscription.metadata['env'] !== this.backendVariables.ENV) break;
|
|
|
|
const existingSubscription = await this.subscriptionsService.get({where : {stripe_subscription_id : stripeSubscription.id}});
|
|
|
|
if(!existingSubscription[0]) break;
|
|
|
|
const subscriptionUpdate: any = {};
|
|
subscriptionUpdate.start_date = new Date(stripeSubscription.current_period_start * 1000);
|
|
subscriptionUpdate.end_date = new Date(stripeSubscription.current_period_end * 1000);
|
|
subscriptionUpdate.nb_seats = stripeSubscription.items.data[0]?.quantity;
|
|
|
|
if(stripeSubscription.items.data[0]?.price?.id === this.backendVariables.STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID || stripeSubscription.items.data[0]?.price?.id === this.backendVariables.STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID){
|
|
subscriptionUpdate.type = "STANDARD";
|
|
}
|
|
else{
|
|
subscriptionUpdate.type = "UNLIMITED";
|
|
}
|
|
|
|
const subscriptionEntityUpdate = Subscription.hydrate<Subscription>(subscriptionUpdate);
|
|
|
|
await validateOrReject(subscriptionEntityUpdate, { groups: ["updateSubscription"], forbidUnknownValues: false });
|
|
|
|
await this.subscriptionsService.update(existingSubscription[0].uid ,subscriptionEntityUpdate);
|
|
|
|
//Manage subscription creation and first payment
|
|
case "checkout.session.completed":
|
|
if (event.data.object.status !== "complete") break;
|
|
|
|
const subscription = JSON.parse(event.data.object.metadata.subscription);
|
|
const env = event.data.object.metadata.env;
|
|
|
|
if (env !== this.backendVariables.ENV) break;
|
|
|
|
subscription.stripe_subscription_id = event.data.object.subscription;
|
|
|
|
await this.stripeService.getClient().subscriptions.update(subscription.stripe_subscription_id, {
|
|
metadata: {
|
|
env: env,
|
|
},
|
|
}
|
|
)
|
|
|
|
const subscriptionInfo = await this.stripeService
|
|
.getClient()
|
|
.subscriptions.retrieve(subscription.stripe_subscription_id);
|
|
|
|
subscription.start_date = new Date(subscriptionInfo.current_period_start * 1000);
|
|
subscription.end_date = new Date(subscriptionInfo.current_period_end * 1000);
|
|
|
|
const subscriptionEntity = Subscription.hydrate<Subscription>(subscription);
|
|
|
|
await validateOrReject(subscriptionEntity, { groups: ["createSubscription"], forbidUnknownValues: false });
|
|
|
|
await this.subscriptionsService.create(subscriptionEntity);
|
|
break;
|
|
|
|
//Manage plan expiration
|
|
case "customer.subscription.deleted":
|
|
const currentSubscription = await this.stripeService.getClient().subscriptions.retrieve(event.data.object.id);
|
|
if(currentSubscription.metadata['env'] !== this.backendVariables.ENV) break;
|
|
const subscriptionToDelete = await this.subscriptionsService.get({where : {stripe_subscription_id : event.data.object.id}});
|
|
if(!subscriptionToDelete[0]) break;
|
|
await this.subscriptionsService.delete(subscriptionToDelete[0].uid);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
response.json({ received: true });
|
|
} catch (error) {
|
|
this.httpInternalError(response, error);
|
|
return;
|
|
}
|
|
}
|
|
}
|