Files
verify/frontend/lib/razorpay.ts
Mohamed Mathar Irfan ed6610d5d8 Initial project upload
2026-07-28 17:57:02 +05:30

84 lines
2.5 KiB
TypeScript

import { api } from "./api";
declare global {
interface Window { Razorpay?: any }
}
function loadScript(): Promise<boolean> {
return new Promise((resolve) => {
if (window.Razorpay) return resolve(true);
const s = document.createElement("script");
s.src = "https://checkout.razorpay.com/v1/checkout.js";
s.onload = () => resolve(true);
s.onerror = () => resolve(false);
document.body.appendChild(s);
});
}
/**
* Start a plan upgrade/downgrade. Creates an order, opens Razorpay checkout
* (or auto-confirms in mock mode), then verifies and activates the plan.
* Returns true on success.
*/
export async function purchasePlan(
planId: string,
coupon?: string,
onSuccess?: (invoiceNumber?: string) => void
): Promise<void> {
const order = await api("/billing/create-order", {
method: "POST",
body: JSON.stringify({ plan_id: planId, coupon: coupon || undefined }),
});
// Free / fully-discounted plan — activated server-side already.
if (order.free) { onSuccess?.(); return; }
// Mock mode (no Razorpay keys): skip the modal, verify directly.
if (order.mock) {
const res = await api("/billing/verify", {
method: "POST",
body: JSON.stringify({
razorpay_order_id: order.order_id,
razorpay_payment_id: `pay_mock_${Date.now()}`,
razorpay_signature: "mock",
plan_id: order.plan_id,
}),
});
onSuccess?.(res.invoice_number);
return;
}
// Live mode — open Razorpay checkout.
const ok = await loadScript();
if (!ok) throw new Error("Failed to load Razorpay checkout");
await new Promise<void>((resolve, reject) => {
const rzp = new window.Razorpay({
key: order.key_id,
amount: order.amount * 100,
currency: order.currency,
name: "VerifyPack",
description: `${order.plan_name} plan`,
order_id: order.order_id,
handler: async (resp: any) => {
try {
const res = await api("/billing/verify", {
method: "POST",
body: JSON.stringify({
razorpay_order_id: resp.razorpay_order_id,
razorpay_payment_id: resp.razorpay_payment_id,
razorpay_signature: resp.razorpay_signature,
plan_id: order.plan_id,
}),
});
onSuccess?.(res.invoice_number);
resolve();
} catch (e) { reject(e); }
},
modal: { ondismiss: () => reject(new Error("Payment cancelled")) },
theme: { color: "#2563eb" },
});
rzp.open();
});
}