@burdenoff/microfe-billing 2026.520.1 → 2026.523.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RazorpayPaymentButton.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/checkout/components/RazorpayPaymentButton.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAoC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EACV,uBAAuB,EAGxB,MAAM,UAAU,CAAC;AASlB,UAAU,0BAA0B;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,
|
|
1
|
+
{"version":3,"file":"RazorpayPaymentButton.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/checkout/components/RazorpayPaymentButton.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAoC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EACV,uBAAuB,EAGxB,MAAM,UAAU,CAAC;AASlB,UAAU,0BAA0B;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CAkOhE,CAAC"}
|
|
@@ -1,162 +1,132 @@
|
|
|
1
1
|
import { getPaymentProviderThemeColor as e } from "../../../shared/utils/paymentTheme.js";
|
|
2
2
|
import "../../../shared/utils/index.js";
|
|
3
3
|
import { useCallback as t, useEffect as n, useState as r } from "react";
|
|
4
|
-
import { AlertCircle as i, Check as a,
|
|
5
|
-
import { Fragment as
|
|
6
|
-
import { useI18n as
|
|
4
|
+
import { AlertCircle as i, Check as a, Loader2 as o, Lock as s } from "lucide-react";
|
|
5
|
+
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
6
|
+
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
7
7
|
//#region src/billing/modules/checkout/components/RazorpayPaymentButton.tsx
|
|
8
|
-
var
|
|
9
|
-
let { t:
|
|
10
|
-
let n =
|
|
8
|
+
var f = ({ orderId: f, keyId: p, amount: m, currency: h, name: g = "Burdenoff", description: _ = "Purchase", customerId: v, prefill: y, notes: b, onSuccess: x, onError: S, onCancel: C, disabled: w = !1 }) => {
|
|
9
|
+
let { t: T } = d(), E = (e, t) => {
|
|
10
|
+
let n = T(e);
|
|
11
11
|
return n === e ? t : n;
|
|
12
|
-
}, [
|
|
12
|
+
}, [D, O] = r("idle"), [k, A] = r(null), [j, M] = r(!1);
|
|
13
13
|
n(() => {
|
|
14
14
|
if (typeof window < "u" && !window.Razorpay) {
|
|
15
15
|
let e = document.createElement("script");
|
|
16
16
|
e.src = "https://checkout.razorpay.com/v1/checkout.js", e.async = !0, e.onload = () => {
|
|
17
|
-
|
|
17
|
+
M(!0);
|
|
18
18
|
}, e.onerror = () => {
|
|
19
|
-
|
|
19
|
+
A("Failed to load payment gateway");
|
|
20
20
|
}, document.body.appendChild(e);
|
|
21
|
-
} else window.Razorpay &&
|
|
21
|
+
} else window.Razorpay && M(!0);
|
|
22
22
|
}, []);
|
|
23
|
-
let
|
|
24
|
-
if (!
|
|
25
|
-
|
|
23
|
+
let N = t(() => {
|
|
24
|
+
if (!j || !window.Razorpay) {
|
|
25
|
+
A("Payment gateway not ready");
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
O("processing"), A(null);
|
|
29
29
|
let t = {
|
|
30
|
-
key:
|
|
31
|
-
amount:
|
|
32
|
-
currency:
|
|
33
|
-
name:
|
|
34
|
-
description:
|
|
35
|
-
order_id:
|
|
36
|
-
prefill:
|
|
37
|
-
notes:
|
|
30
|
+
key: p,
|
|
31
|
+
amount: m,
|
|
32
|
+
currency: h.toUpperCase(),
|
|
33
|
+
name: g,
|
|
34
|
+
description: _,
|
|
35
|
+
order_id: f,
|
|
36
|
+
prefill: y || {},
|
|
37
|
+
notes: b || {},
|
|
38
38
|
handler: (e) => {
|
|
39
|
-
|
|
39
|
+
O("success"), x(e);
|
|
40
40
|
},
|
|
41
41
|
modal: {
|
|
42
42
|
ondismiss: () => {
|
|
43
|
-
|
|
43
|
+
O("idle"), C?.();
|
|
44
44
|
},
|
|
45
45
|
escape: !0,
|
|
46
46
|
confirm_close: !0
|
|
47
47
|
}
|
|
48
48
|
}, n = e();
|
|
49
|
-
n && (t.theme = { color: n }),
|
|
49
|
+
n && (t.theme = { color: n }), v && (t.customer_id = v, t.remember_customer = !0);
|
|
50
50
|
try {
|
|
51
51
|
let e = window.Razorpay;
|
|
52
52
|
if (!e) throw Error("Payment gateway not ready");
|
|
53
53
|
let n = new e(t);
|
|
54
54
|
n.on("payment.failed", (e) => {
|
|
55
55
|
let t = e, n = t?.error?.description || t?.error?.reason || "Payment failed";
|
|
56
|
-
|
|
56
|
+
A(n), O("error"), S(n);
|
|
57
57
|
}), n.open();
|
|
58
58
|
} catch (e) {
|
|
59
59
|
let t = e instanceof Error ? e.message : "Failed to open payment gateway";
|
|
60
|
-
|
|
60
|
+
A(t), O("error"), S(t);
|
|
61
61
|
}
|
|
62
62
|
}, [
|
|
63
|
-
|
|
63
|
+
j,
|
|
64
|
+
p,
|
|
65
|
+
m,
|
|
64
66
|
h,
|
|
65
67
|
g,
|
|
66
68
|
_,
|
|
67
69
|
v,
|
|
70
|
+
f,
|
|
68
71
|
y,
|
|
69
72
|
b,
|
|
70
|
-
m,
|
|
71
73
|
x,
|
|
72
74
|
S,
|
|
73
|
-
C
|
|
74
|
-
|
|
75
|
-
T
|
|
76
|
-
]), I = (g / 100).toLocaleString("en-IN", {
|
|
75
|
+
C
|
|
76
|
+
]), P = (m / 100).toLocaleString("en-IN", {
|
|
77
77
|
style: "currency",
|
|
78
78
|
currency: "INR"
|
|
79
79
|
});
|
|
80
|
-
return
|
|
80
|
+
return D === "success" ? /* @__PURE__ */ l("div", {
|
|
81
81
|
className: "p-6 rounded-lg border border-border-subtle bg-status-success-bg-subtle",
|
|
82
|
-
children: /* @__PURE__ */
|
|
82
|
+
children: /* @__PURE__ */ u("div", {
|
|
83
83
|
className: "flex items-center gap-3",
|
|
84
|
-
children: [/* @__PURE__ */
|
|
84
|
+
children: [/* @__PURE__ */ l("div", {
|
|
85
85
|
className: "p-2 rounded-full bg-status-success-bg-subtle text-status-success-text",
|
|
86
|
-
children: /* @__PURE__ */
|
|
87
|
-
}), /* @__PURE__ */
|
|
86
|
+
children: /* @__PURE__ */ l(a, { className: "h-6 w-6" })
|
|
87
|
+
}), /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h3", {
|
|
88
88
|
className: "font-semibold text-status-success-text",
|
|
89
89
|
children: "Payment Successful!"
|
|
90
|
-
}), /* @__PURE__ */
|
|
90
|
+
}), /* @__PURE__ */ l("p", {
|
|
91
91
|
className: "text-sm text-status-success-text",
|
|
92
92
|
children: "Your payment has been processed successfully."
|
|
93
93
|
})] })]
|
|
94
94
|
})
|
|
95
|
-
}) : /* @__PURE__ */
|
|
95
|
+
}) : /* @__PURE__ */ u("div", {
|
|
96
96
|
className: "space-y-4",
|
|
97
97
|
children: [
|
|
98
|
-
/* @__PURE__ */
|
|
99
|
-
className: "flex items-center justify-
|
|
100
|
-
children: [/* @__PURE__ */
|
|
101
|
-
className: "flex items-center gap-2",
|
|
102
|
-
children: [/* @__PURE__ */ f("div", {
|
|
103
|
-
className: "flex items-center gap-1",
|
|
104
|
-
children: [/* @__PURE__ */ d(o, { className: "h-5 w-5 text-muted-foreground" }), /* @__PURE__ */ d(l, { className: "h-4 w-4 text-muted-foreground" })]
|
|
105
|
-
}), /* @__PURE__ */ d("span", {
|
|
106
|
-
className: "font-medium text-foreground",
|
|
107
|
-
children: "Razorpay Payment"
|
|
108
|
-
})]
|
|
109
|
-
}), /* @__PURE__ */ f("div", {
|
|
110
|
-
className: "flex items-center gap-1 text-xs text-muted-foreground",
|
|
111
|
-
children: [/* @__PURE__ */ d(c, { className: "h-3 w-3" }), "Secured by Razorpay"]
|
|
112
|
-
})]
|
|
113
|
-
}),
|
|
114
|
-
/* @__PURE__ */ f("div", {
|
|
115
|
-
className: "p-4 rounded-lg border border-border bg-muted/30",
|
|
116
|
-
children: [/* @__PURE__ */ d("p", {
|
|
117
|
-
className: "text-sm text-muted-foreground mb-3",
|
|
118
|
-
children: "Pay using any of these methods:"
|
|
119
|
-
}), /* @__PURE__ */ d("div", {
|
|
120
|
-
className: "grid grid-cols-2 sm:grid-cols-4 gap-2",
|
|
121
|
-
children: [
|
|
122
|
-
"UPI",
|
|
123
|
-
"Cards",
|
|
124
|
-
"Netbanking",
|
|
125
|
-
"Wallets"
|
|
126
|
-
].map((e) => /* @__PURE__ */ d("div", {
|
|
127
|
-
className: "px-3 py-2 rounded border border-border bg-background text-center text-sm text-foreground",
|
|
128
|
-
children: e
|
|
129
|
-
}, e))
|
|
130
|
-
})]
|
|
98
|
+
/* @__PURE__ */ u("div", {
|
|
99
|
+
className: "flex items-center justify-center gap-1.5 text-xs text-muted-foreground",
|
|
100
|
+
children: [/* @__PURE__ */ l(s, { className: "h-3 w-3" }), "Secured by Razorpay"]
|
|
131
101
|
}),
|
|
132
|
-
|
|
102
|
+
k && /* @__PURE__ */ u("div", {
|
|
133
103
|
className: "flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm",
|
|
134
|
-
children: [/* @__PURE__ */
|
|
104
|
+
children: [/* @__PURE__ */ l(i, { className: "h-4 w-4 shrink-0" }), k]
|
|
135
105
|
}),
|
|
136
|
-
!
|
|
106
|
+
!j && /* @__PURE__ */ u("div", {
|
|
137
107
|
className: "flex items-center justify-center gap-2 py-4 text-muted-foreground",
|
|
138
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ l(o, { className: "h-4 w-4 animate-spin" }), /* @__PURE__ */ l("span", {
|
|
139
109
|
className: "text-sm",
|
|
140
|
-
children:
|
|
110
|
+
children: E("billing.checkout.loadingGateway", "Loading payment gateway...")
|
|
141
111
|
})]
|
|
142
112
|
}),
|
|
143
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ u("div", {
|
|
144
114
|
className: "flex gap-3",
|
|
145
|
-
children: [
|
|
115
|
+
children: [C && /* @__PURE__ */ l("button", {
|
|
146
116
|
type: "button",
|
|
147
|
-
onClick:
|
|
148
|
-
disabled:
|
|
117
|
+
onClick: C,
|
|
118
|
+
disabled: D === "processing" || w,
|
|
149
119
|
className: "flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
150
120
|
children: "Cancel"
|
|
151
|
-
}), /* @__PURE__ */
|
|
121
|
+
}), /* @__PURE__ */ l("button", {
|
|
152
122
|
type: "button",
|
|
153
|
-
onClick:
|
|
154
|
-
disabled: !
|
|
123
|
+
onClick: N,
|
|
124
|
+
disabled: !j || D === "processing" || w,
|
|
155
125
|
className: "flex-1 px-4 py-3 rounded-lg bg-action-primary-bg text-action-primary-text font-medium\n hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2",
|
|
156
|
-
children:
|
|
126
|
+
children: D === "processing" ? /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ l(o, { className: "h-4 w-4 animate-spin" }), "Processing..."] }) : /* @__PURE__ */ u(c, { children: ["Pay ", P] })
|
|
157
127
|
})]
|
|
158
128
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
129
|
+
/* @__PURE__ */ l("p", {
|
|
160
130
|
className: "text-center text-xs text-muted-foreground",
|
|
161
131
|
children: "Your payment is secured with 256-bit encryption. Powered by Razorpay."
|
|
162
132
|
})
|
|
@@ -164,6 +134,6 @@ var m = ({ orderId: m, keyId: h, amount: g, currency: _, name: v = "Burdenoff",
|
|
|
164
134
|
});
|
|
165
135
|
};
|
|
166
136
|
//#endregion
|
|
167
|
-
export {
|
|
137
|
+
export { f as RazorpayPaymentButton };
|
|
168
138
|
|
|
169
139
|
//# sourceMappingURL=RazorpayPaymentButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RazorpayPaymentButton.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/RazorpayPaymentButton.tsx"],"sourcesContent":["/**\n * {tr('billing.checkout.razorpayPayment', 'Razorpay Payment')} Button Component\n * Integrates with Razorpay checkout for INR payments\n */\n\nimport { type FC, useState, useCallback, useEffect } from 'react';\nimport { CreditCard, Lock, Loader2, Check, AlertCircle, Smartphone } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type {\n RazorpaySuccessResponse,\n CheckoutRazorpayOptions,\n CheckoutRazorpayInstance,\n} from '../types';\nimport { getPaymentProviderThemeColor } from '../../../shared/utils';\n\ntype RazorpayCheckoutOptions = CheckoutRazorpayOptions & {\n customer_id?: string;\n remember_customer?: boolean;\n handler: (response: RazorpaySuccessResponse) => void;\n};\n\ninterface RazorpayPaymentButtonProps {\n orderId: string;\n keyId: string;\n amount: number; // In paise (smallest currency unit)\n currency: string;\n name?: string;\n description?: string;\n customerId?: string; // Razorpay customer ID for saved cards\n prefill?: {\n name?: string;\n email?: string;\n contact?: string;\n };\n notes?: Record<string, string>;\n onSuccess: (response: RazorpaySuccessResponse) => void;\n onError: (error: string) => void;\n onCancel?: () => void;\n disabled?: boolean;\n}\n\ntype PaymentState = 'idle' | 'loading' | 'processing' | 'success' | 'error';\n\nexport const RazorpayPaymentButton: FC<RazorpayPaymentButtonProps> = ({\n orderId,\n keyId,\n amount,\n currency,\n name = 'Burdenoff',\n description = 'Purchase',\n customerId,\n prefill,\n notes,\n onSuccess,\n onError,\n onCancel,\n disabled = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [paymentState, setPaymentState] = useState<PaymentState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [isRazorpayLoaded, setIsRazorpayLoaded] = useState(false);\n\n // Load Razorpay SDK dynamically\n useEffect(() => {\n if (typeof window !== 'undefined' && !window.Razorpay) {\n const script = document.createElement('script');\n script.src = 'https://checkout.razorpay.com/v1/checkout.js';\n script.async = true;\n script.onload = () => {\n setIsRazorpayLoaded(true);\n };\n script.onerror = () => {\n setError('Failed to load payment gateway');\n };\n document.body.appendChild(script);\n } else if (window.Razorpay) {\n setIsRazorpayLoaded(true);\n }\n }, []);\n\n const handlePayment = useCallback(() => {\n if (!isRazorpayLoaded || !window.Razorpay) {\n setError('Payment gateway not ready');\n return;\n }\n\n setPaymentState('processing');\n setError(null);\n\n // Build Razorpay options - customer_id enables saved cards feature\n const options: RazorpayCheckoutOptions = {\n key: keyId,\n amount: amount, // Amount in paise\n currency: currency.toUpperCase(),\n name,\n description,\n order_id: orderId,\n prefill: prefill || {},\n notes: notes || {},\n handler: (response: RazorpaySuccessResponse) => {\n setPaymentState('success');\n onSuccess(response);\n },\n modal: {\n ondismiss: () => {\n setPaymentState('idle');\n onCancel?.();\n },\n escape: true,\n confirm_close: true,\n },\n };\n\n const providerThemeColor = getPaymentProviderThemeColor();\n if (providerThemeColor) {\n options.theme = { color: providerThemeColor };\n }\n\n // Add customer_id for saved cards feature\n if (customerId) {\n options.customer_id = customerId;\n options.remember_customer = true;\n }\n\n try {\n const RazorpayConstructor = (\n window as unknown as {\n Razorpay?: new (options: RazorpayCheckoutOptions) => CheckoutRazorpayInstance;\n }\n ).Razorpay;\n\n if (!RazorpayConstructor) {\n throw new Error('Payment gateway not ready');\n }\n\n const razorpay = new RazorpayConstructor(options);\n\n razorpay.on('payment.failed', (response: unknown) => {\n const errorResponse = response as {\n error?: {\n code?: string;\n description?: string;\n reason?: string;\n };\n };\n const errorMessage =\n errorResponse?.error?.description || errorResponse?.error?.reason || 'Payment failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n });\n\n razorpay.open();\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to open payment gateway';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n }, [\n isRazorpayLoaded,\n keyId,\n amount,\n currency,\n name,\n description,\n customerId,\n orderId,\n prefill,\n notes,\n onSuccess,\n onError,\n onCancel,\n ]);\n\n // Format amount for display (convert from paise to rupees)\n const displayAmount = (amount / 100).toLocaleString('en-IN', {\n style: 'currency',\n currency: 'INR',\n });\n\n // Render success state\n if (paymentState === 'success') {\n return (\n <div className=\"p-6 rounded-lg border border-border-subtle bg-status-success-bg-subtle\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Check className=\"h-6 w-6\" />\n </div>\n <div>\n <h3 className=\"font-semibold text-status-success-text\">Payment Successful!</h3>\n <p className=\"text-sm text-status-success-text\">\n Your payment has been processed successfully.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex items-center gap-1\">\n <CreditCard className=\"h-5 w-5 text-muted-foreground\" />\n <Smartphone className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n <span className=\"font-medium text-foreground\">Razorpay Payment</span>\n </div>\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <Lock className=\"h-3 w-3\" />\n Secured by Razorpay\n </div>\n </div>\n\n {/* Payment methods info */}\n <div className=\"p-4 rounded-lg border border-border bg-muted/30\">\n <p className=\"text-sm text-muted-foreground mb-3\">Pay using any of these methods:</p>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-2\">\n {['UPI', 'Cards', 'Netbanking', 'Wallets'].map((method) => (\n <div\n key={method}\n className=\"px-3 py-2 rounded border border-border bg-background text-center text-sm text-foreground\"\n >\n {method}\n </div>\n ))}\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm\">\n <AlertCircle className=\"h-4 w-4 shrink-0\" />\n {error}\n </div>\n )}\n\n {/* Loading state */}\n {!isRazorpayLoaded && (\n <div className=\"flex items-center justify-center gap-2 py-4 text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm\">\n {tr('billing.checkout.loadingGateway', 'Loading payment gateway...')}\n </span>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Cancel\n </button>\n )}\n <button\n type=\"button\"\n onClick={handlePayment}\n disabled={!isRazorpayLoaded || paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg bg-action-primary-bg text-action-primary-text font-medium\n hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2\"\n >\n {paymentState === 'processing' ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n Processing...\n </>\n ) : (\n <>Pay {displayAmount}</>\n )}\n </button>\n </div>\n\n {/* Security note */}\n <p className=\"text-center text-xs text-muted-foreground\">\n Your payment is secured with 256-bit encryption. Powered by Razorpay.\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RazorpayPaymentButton.js","names":[],"sources":["../../../../../src/billing/modules/checkout/components/RazorpayPaymentButton.tsx"],"sourcesContent":["/**\n * {tr('billing.checkout.razorpayPayment', 'Razorpay Payment')} Button Component\n * Integrates with Razorpay checkout for INR payments\n */\n\nimport { type FC, useState, useCallback, useEffect } from 'react';\nimport { Lock, Loader2, Check, AlertCircle } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type {\n RazorpaySuccessResponse,\n CheckoutRazorpayOptions,\n CheckoutRazorpayInstance,\n} from '../types';\nimport { getPaymentProviderThemeColor } from '../../../shared/utils';\n\ntype RazorpayCheckoutOptions = CheckoutRazorpayOptions & {\n customer_id?: string;\n remember_customer?: boolean;\n handler: (response: RazorpaySuccessResponse) => void;\n};\n\ninterface RazorpayPaymentButtonProps {\n orderId: string;\n keyId: string;\n amount: number; // In paise (smallest currency unit)\n currency: string;\n name?: string;\n description?: string;\n customerId?: string; // Razorpay customer ID for saved cards\n prefill?: {\n name?: string;\n email?: string;\n contact?: string;\n };\n notes?: Record<string, string>;\n onSuccess: (response: RazorpaySuccessResponse) => void;\n onError: (error: string) => void;\n onCancel?: () => void;\n disabled?: boolean;\n}\n\ntype PaymentState = 'idle' | 'loading' | 'processing' | 'success' | 'error';\n\nexport const RazorpayPaymentButton: FC<RazorpayPaymentButtonProps> = ({\n orderId,\n keyId,\n amount,\n currency,\n name = 'Burdenoff',\n description = 'Purchase',\n customerId,\n prefill,\n notes,\n onSuccess,\n onError,\n onCancel,\n disabled = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const [paymentState, setPaymentState] = useState<PaymentState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [isRazorpayLoaded, setIsRazorpayLoaded] = useState(false);\n\n // Load Razorpay SDK dynamically\n useEffect(() => {\n if (typeof window !== 'undefined' && !window.Razorpay) {\n const script = document.createElement('script');\n script.src = 'https://checkout.razorpay.com/v1/checkout.js';\n script.async = true;\n script.onload = () => {\n setIsRazorpayLoaded(true);\n };\n script.onerror = () => {\n setError('Failed to load payment gateway');\n };\n document.body.appendChild(script);\n } else if (window.Razorpay) {\n setIsRazorpayLoaded(true);\n }\n }, []);\n\n const handlePayment = useCallback(() => {\n if (!isRazorpayLoaded || !window.Razorpay) {\n setError('Payment gateway not ready');\n return;\n }\n\n setPaymentState('processing');\n setError(null);\n\n // Build Razorpay options - customer_id enables saved cards feature\n const options: RazorpayCheckoutOptions = {\n key: keyId,\n amount: amount, // Amount in paise\n currency: currency.toUpperCase(),\n name,\n description,\n order_id: orderId,\n prefill: prefill || {},\n notes: notes || {},\n handler: (response: RazorpaySuccessResponse) => {\n setPaymentState('success');\n onSuccess(response);\n },\n modal: {\n ondismiss: () => {\n setPaymentState('idle');\n onCancel?.();\n },\n escape: true,\n confirm_close: true,\n },\n };\n\n const providerThemeColor = getPaymentProviderThemeColor();\n if (providerThemeColor) {\n options.theme = { color: providerThemeColor };\n }\n\n // Add customer_id for saved cards feature\n if (customerId) {\n options.customer_id = customerId;\n options.remember_customer = true;\n }\n\n try {\n const RazorpayConstructor = (\n window as unknown as {\n Razorpay?: new (options: RazorpayCheckoutOptions) => CheckoutRazorpayInstance;\n }\n ).Razorpay;\n\n if (!RazorpayConstructor) {\n throw new Error('Payment gateway not ready');\n }\n\n const razorpay = new RazorpayConstructor(options);\n\n razorpay.on('payment.failed', (response: unknown) => {\n const errorResponse = response as {\n error?: {\n code?: string;\n description?: string;\n reason?: string;\n };\n };\n const errorMessage =\n errorResponse?.error?.description || errorResponse?.error?.reason || 'Payment failed';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n });\n\n razorpay.open();\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to open payment gateway';\n setError(errorMessage);\n setPaymentState('error');\n onError(errorMessage);\n }\n }, [\n isRazorpayLoaded,\n keyId,\n amount,\n currency,\n name,\n description,\n customerId,\n orderId,\n prefill,\n notes,\n onSuccess,\n onError,\n onCancel,\n ]);\n\n // Format amount for display (convert from paise to rupees)\n const displayAmount = (amount / 100).toLocaleString('en-IN', {\n style: 'currency',\n currency: 'INR',\n });\n\n // Render success state\n if (paymentState === 'success') {\n return (\n <div className=\"p-6 rounded-lg border border-border-subtle bg-status-success-bg-subtle\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Check className=\"h-6 w-6\" />\n </div>\n <div>\n <h3 className=\"font-semibold text-status-success-text\">Payment Successful!</h3>\n <p className=\"text-sm text-status-success-text\">\n Your payment has been processed successfully.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Security badge */}\n <div className=\"flex items-center justify-center gap-1.5 text-xs text-muted-foreground\">\n <Lock className=\"h-3 w-3\" />\n Secured by Razorpay\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm\">\n <AlertCircle className=\"h-4 w-4 shrink-0\" />\n {error}\n </div>\n )}\n\n {/* Loading state */}\n {!isRazorpayLoaded && (\n <div className=\"flex items-center justify-center gap-2 py-4 text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span className=\"text-sm\">\n {tr('billing.checkout.loadingGateway', 'Loading payment gateway...')}\n </span>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg border border-border text-foreground font-medium\n hover:bg-muted disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Cancel\n </button>\n )}\n <button\n type=\"button\"\n onClick={handlePayment}\n disabled={!isRazorpayLoaded || paymentState === 'processing' || disabled}\n className=\"flex-1 px-4 py-3 rounded-lg bg-action-primary-bg text-action-primary-text font-medium\n hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\n flex items-center justify-center gap-2\"\n >\n {paymentState === 'processing' ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n Processing...\n </>\n ) : (\n <>Pay {displayAmount}</>\n )}\n </button>\n </div>\n\n {/* Security note */}\n <p className=\"text-center text-xs text-muted-foreground\">\n Your payment is secured with 256-bit encryption. Powered by Razorpay.\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
|