import { Router } from "express"; import { z } from "zod"; import { authorize, requireAuth } from "../middleware/auth"; import { createInvoicePaymentLink, handleManualInvoicePayment, processFlutterwaveWebhook, processPaystackWebhook, verifyFlutterwaveSignature, verifyPaystackSignature } from "../services/payment.service"; const router = Router(); const createLinkSchema = z.object({ provider: z.enum(["paystack", "flutterwave", "manual"]).optional() }); router.post("/invoices/:id/link", requireAuth, authorize("billing:manage"), async (req, res, next) => { try { const payload = createLinkSchema.parse(req.body ?? {}); const result = await createInvoicePaymentLink(req.params.id, payload.provider); res.json(result); } catch (error) { next(error); } }); const manualSchema = z.object({ payment_reference: z.string().min(2) }); router.post("/invoices/:id/manual-pay", requireAuth, authorize("billing:manage"), async (req, res, next) => { try { const payload = manualSchema.parse(req.body ?? {}); const invoice = await handleManualInvoicePayment(req.params.id, payload.payment_reference, req.user?.email ?? "manual@system"); res.json(invoice); } catch (error) { next(error); } }); router.post("/webhooks/paystack", async (req, res, next) => { try { const signature = req.header("x-paystack-signature"); const valid = await verifyPaystackSignature(signature, req.rawBody); if (!valid) { return res.status(401).json({ error: { code: "INVALID_SIGNATURE", message: "Invalid signature" } }); } const result = await processPaystackWebhook(req.body); return res.json(result); } catch (error) { return next(error); } }); router.post("/webhooks/flutterwave", async (req, res, next) => { try { const signature = req.header("verif-hash"); const valid = await verifyFlutterwaveSignature(signature); if (!valid) { return res.status(401).json({ error: { code: "INVALID_SIGNATURE", message: "Invalid signature" } }); } const result = await processFlutterwaveWebhook(req.body); return res.json(result); } catch (error) { return next(error); } }); export default router;