84 lines
2.5 KiB
TypeScript
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();
|
|
});
|
|
}
|