alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
121 lines (114 loc) • 3.38 kB
text/typescript
import { $inject, z } from "alepha";
import { $secure } from "alepha/security";
import { $action, okSchema } from "alepha/server";
import { PaymentError } from "../errors/PaymentError.ts";
import {
checkoutResponseSchema,
createCheckoutSchema,
} from "../schemas/intentSchemas.ts";
import {
addPaymentMethodSchema,
paymentMethodResourceSchema,
} from "../schemas/paymentMethodSchemas.ts";
import { PaymentMethodService } from "../services/PaymentMethodService.ts";
import { PaymentService } from "../services/PaymentService.ts";
export class PaymentController {
protected readonly url = "/payments";
protected readonly group = "payments";
protected readonly payments = $inject(PaymentService);
protected readonly paymentMethods = $inject(PaymentMethodService);
/**
* List the current user's saved payment methods.
*/
public readonly listPaymentMethods = $action({
path: `${this.url}/payment-methods`,
group: this.group,
use: [$secure()],
description: "List current user's saved payment methods",
schema: {
response: z.array(paymentMethodResourceSchema),
},
handler: ({ user }) => this.paymentMethods.listPaymentMethods(user.id),
});
/**
* Add a new payment method.
*/
public readonly addPaymentMethod = $action({
method: "POST",
path: `${this.url}/payment-methods`,
group: this.group,
use: [$secure()],
description: "Tokenize and store a new payment method",
schema: {
body: addPaymentMethodSchema,
response: paymentMethodResourceSchema,
},
handler: ({ body, user }) => {
if (!user.organization) {
throw new PaymentError(
"Organization is required to add a payment method",
);
}
return this.paymentMethods.addPaymentMethod(
user.id,
user.organization,
body.token,
);
},
});
/**
* Remove a payment method.
*/
public readonly removePaymentMethod = $action({
method: "DELETE",
path: `${this.url}/payment-methods/:id`,
group: this.group,
use: [$secure()],
description: "Remove own payment method",
schema: {
params: z.object({ id: z.uuid() }),
response: okSchema,
},
handler: async ({ params, user }) => {
await this.paymentMethods.removePaymentMethod(params.id, user.id);
return { ok: true, id: params.id };
},
});
/**
* Set a payment method as default.
*/
public readonly setDefaultPaymentMethod = $action({
method: "PATCH",
path: `${this.url}/payment-methods/:id/default`,
group: this.group,
use: [$secure()],
description: "Set as default payment method",
schema: {
params: z.object({ id: z.uuid() }),
response: paymentMethodResourceSchema,
},
handler: ({ params, user }) =>
this.paymentMethods.setDefault(params.id, user.id),
});
/**
* Create a checkout session.
*/
public readonly createCheckout = $action({
method: "POST",
path: `${this.url}/checkout`,
group: this.group,
use: [$secure()],
description: "Create checkout session and return URL",
schema: {
body: createCheckoutSchema,
response: checkoutResponseSchema,
},
handler: ({ body, user }) =>
this.payments.createSession(
body.intentId,
body.returnUrl,
body.authorize,
user.id,
),
});
}