UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

155 lines (145 loc) 4.33 kB
import { $inject, z } from "alepha"; import { $secure } from "alepha/security"; import { $action, okSchema } from "alepha/server"; import { captureIntentSchema, intentQuerySchema, intentResourceSchema, recordCashSchema, refundIntentSchema, } from "../schemas/intentSchemas.ts"; import { refundResourceSchema } from "../schemas/refundSchemas.ts"; import { PaymentService } from "../services/PaymentService.ts"; export class AdminPaymentController { protected readonly url = "/admin/payments"; protected readonly group = "admin:payments"; protected readonly payments = $inject(PaymentService); /** * List payment intents with pagination and filtering. */ public readonly listIntents = $action({ path: `${this.url}/intents`, group: this.group, use: [$secure({ permissions: ["payments:read"] })], description: "List payment intents", schema: { query: intentQuerySchema, response: z.page(intentResourceSchema), }, handler: ({ query }) => this.payments.findIntents(query), }); /** * Get a payment intent by ID. */ public readonly getIntent = $action({ path: `${this.url}/intents/:id`, group: this.group, use: [$secure({ permissions: ["payments:read"] })], description: "Get payment intent details", schema: { params: z.object({ id: z.uuid() }), response: intentResourceSchema, }, handler: ({ params }) => this.payments.getIntent(params.id), }); /** * Capture an authorized intent. */ public readonly captureIntent = $action({ method: "POST", path: `${this.url}/intents/:id/capture`, group: this.group, use: [$secure({ permissions: ["payments:write"] })], description: "Capture an authorized payment intent", schema: { params: z.object({ id: z.uuid() }), body: captureIntentSchema, response: intentResourceSchema, }, handler: ({ params, body }) => this.payments.capture(params.id, body.amount), }); /** * Void an authorized intent. */ public readonly voidIntent = $action({ method: "POST", path: `${this.url}/intents/:id/void`, group: this.group, use: [$secure({ permissions: ["payments:write"] })], description: "Void an authorized payment intent", schema: { params: z.object({ id: z.uuid() }), response: intentResourceSchema, }, handler: ({ params }) => this.payments.void(params.id), }); /** * Refund a captured intent. */ public readonly refundIntent = $action({ method: "POST", path: `${this.url}/intents/:id/refund`, group: this.group, use: [$secure({ permissions: ["payments:write"] })], description: "Issue partial or full refund", schema: { params: z.object({ id: z.uuid() }), body: refundIntentSchema, response: refundResourceSchema, }, handler: ({ params, body }) => this.payments.refund(params.id, body.amount, body.reason), }); /** * Cancel a created intent. */ public readonly cancelIntent = $action({ method: "POST", path: `${this.url}/intents/:id/cancel`, group: this.group, use: [$secure({ permissions: ["payments:write"] })], description: "Cancel a created payment intent", schema: { params: z.object({ id: z.uuid() }), response: intentResourceSchema, }, handler: ({ params }) => this.payments.cancel(params.id), }); /** * Record a cash payment. */ public readonly recordCash = $action({ method: "POST", path: `${this.url}/cash`, group: this.group, use: [$secure({ permissions: ["payments:write"] })], description: "Record a cash payment", schema: { body: recordCashSchema, response: intentResourceSchema, }, handler: ({ body }) => this.payments.recordCashPayment( body.amount, body.currency, body.metadata, ), }); /** * PSP webhook endpoint (not under /admin, no auth — verified by provider). */ public readonly webhook = $action({ method: "POST", path: "/payments/webhook", group: this.group, description: "PSP webhook endpoint", schema: { response: okSchema, }, handler: async (request) => { await this.payments.handleWebhook(request.raw.web!.req); return { ok: true }; }, }); }