@seedhape/react 0.1.0
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.
- package/dist/index.cjs +412 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +72 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.mjs +381 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +37 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PaymentButton: () => PaymentButton,
|
|
24
|
+
PaymentModal: () => PaymentModal,
|
|
25
|
+
SeedhaPeProvider: () => SeedhaPeProvider,
|
|
26
|
+
usePayment: () => usePayment,
|
|
27
|
+
useSeedhaPe: () => useSeedhaPe
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/provider.tsx
|
|
32
|
+
var import_react = require("react");
|
|
33
|
+
var import_sdk = require("@seedhape/sdk");
|
|
34
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
var SeedhaPeContext = (0, import_react.createContext)(null);
|
|
36
|
+
function SeedhaPeProvider({
|
|
37
|
+
apiKey,
|
|
38
|
+
baseUrl,
|
|
39
|
+
children
|
|
40
|
+
}) {
|
|
41
|
+
const client = (0, import_react.useMemo)(() => {
|
|
42
|
+
const config = { apiKey };
|
|
43
|
+
if (baseUrl) config.baseUrl = baseUrl;
|
|
44
|
+
return new import_sdk.SeedhaPe(config);
|
|
45
|
+
}, [apiKey, baseUrl]);
|
|
46
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SeedhaPeContext.Provider, { value: { client }, children });
|
|
47
|
+
}
|
|
48
|
+
function useSeedhaPe() {
|
|
49
|
+
const ctx = (0, import_react.useContext)(SeedhaPeContext);
|
|
50
|
+
if (!ctx) throw new Error("useSeedhaPe must be used inside <SeedhaPeProvider>");
|
|
51
|
+
return ctx.client;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/PaymentButton.tsx
|
|
55
|
+
var import_react3 = require("react");
|
|
56
|
+
|
|
57
|
+
// src/PaymentModal.tsx
|
|
58
|
+
var import_react2 = require("react");
|
|
59
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
60
|
+
var API_URL = typeof __SEEDHAPE_API_URL__ !== "undefined" ? __SEEDHAPE_API_URL__ : "https://api.seedhape.com";
|
|
61
|
+
var TERMINAL = ["VERIFIED", "RESOLVED", "EXPIRED", "REJECTED"];
|
|
62
|
+
var baseStyles = {
|
|
63
|
+
overlay: {
|
|
64
|
+
position: "fixed",
|
|
65
|
+
inset: 0,
|
|
66
|
+
background: "rgba(0,0,0,0.5)",
|
|
67
|
+
display: "flex",
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
justifyContent: "center",
|
|
70
|
+
zIndex: 99999,
|
|
71
|
+
fontFamily: "system-ui, sans-serif"
|
|
72
|
+
},
|
|
73
|
+
card: {
|
|
74
|
+
background: "white",
|
|
75
|
+
borderRadius: 16,
|
|
76
|
+
padding: 28,
|
|
77
|
+
width: 360,
|
|
78
|
+
maxWidth: "calc(100vw - 32px)",
|
|
79
|
+
textAlign: "center",
|
|
80
|
+
boxShadow: "0 25px 50px rgba(0,0,0,0.2)"
|
|
81
|
+
},
|
|
82
|
+
amountBox: {
|
|
83
|
+
background: "#f0fdf4",
|
|
84
|
+
borderRadius: 12,
|
|
85
|
+
padding: "12px 16px",
|
|
86
|
+
marginBottom: 20
|
|
87
|
+
},
|
|
88
|
+
amountLabel: { fontSize: 12, color: "#15803d", marginBottom: 2 },
|
|
89
|
+
amount: { fontSize: 28, fontWeight: 700, color: "#14532d", margin: 0 },
|
|
90
|
+
input: {
|
|
91
|
+
width: "100%",
|
|
92
|
+
border: "1.5px solid #d1d5db",
|
|
93
|
+
borderRadius: 10,
|
|
94
|
+
padding: "10px 12px",
|
|
95
|
+
fontSize: 14,
|
|
96
|
+
boxSizing: "border-box",
|
|
97
|
+
outline: "none",
|
|
98
|
+
marginBottom: 8
|
|
99
|
+
},
|
|
100
|
+
inputError: { borderColor: "#f87171" },
|
|
101
|
+
btnPrimary: {
|
|
102
|
+
width: "100%",
|
|
103
|
+
background: "#16a34a",
|
|
104
|
+
color: "white",
|
|
105
|
+
border: "none",
|
|
106
|
+
borderRadius: 12,
|
|
107
|
+
padding: "12px 0",
|
|
108
|
+
fontSize: 15,
|
|
109
|
+
fontWeight: 600,
|
|
110
|
+
cursor: "pointer",
|
|
111
|
+
display: "flex",
|
|
112
|
+
alignItems: "center",
|
|
113
|
+
justifyContent: "center",
|
|
114
|
+
gap: 8
|
|
115
|
+
},
|
|
116
|
+
btnDisabled: { opacity: 0.5, cursor: "not-allowed" },
|
|
117
|
+
closeBtn: {
|
|
118
|
+
marginTop: 14,
|
|
119
|
+
background: "none",
|
|
120
|
+
border: "none",
|
|
121
|
+
color: "#9ca3af",
|
|
122
|
+
fontSize: 13,
|
|
123
|
+
cursor: "pointer"
|
|
124
|
+
},
|
|
125
|
+
hint: { fontSize: 12, color: "#6b7280", lineHeight: 1.5, marginBottom: 12, textAlign: "left" },
|
|
126
|
+
errorText: { fontSize: 12, color: "#ef4444", marginBottom: 8, textAlign: "left" },
|
|
127
|
+
stepDots: { display: "flex", justifyContent: "center", gap: 6, marginTop: 14 },
|
|
128
|
+
dot: (active) => ({
|
|
129
|
+
width: 24,
|
|
130
|
+
height: 6,
|
|
131
|
+
borderRadius: 3,
|
|
132
|
+
background: active ? "#16a34a" : "#e5e7eb"
|
|
133
|
+
})
|
|
134
|
+
};
|
|
135
|
+
function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }) {
|
|
136
|
+
const [order, setOrder] = (0, import_react2.useState)(null);
|
|
137
|
+
const [nameInput, setNameInput] = (0, import_react2.useState)("");
|
|
138
|
+
const [nameError, setNameError] = (0, import_react2.useState)(null);
|
|
139
|
+
const [savingName, setSavingName] = (0, import_react2.useState)(false);
|
|
140
|
+
const [nameConfirmed, setNameConfirmed] = (0, import_react2.useState)(false);
|
|
141
|
+
const pollRef = (0, import_react2.useRef)(null);
|
|
142
|
+
(0, import_react2.useEffect)(() => {
|
|
143
|
+
if (!open || !orderId) return;
|
|
144
|
+
setOrder(null);
|
|
145
|
+
setNameInput("");
|
|
146
|
+
setNameError(null);
|
|
147
|
+
setNameConfirmed(false);
|
|
148
|
+
fetchOrder();
|
|
149
|
+
return () => {
|
|
150
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
151
|
+
};
|
|
152
|
+
}, [open, orderId]);
|
|
153
|
+
async function fetchOrder() {
|
|
154
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
|
|
155
|
+
if (!res.ok) return;
|
|
156
|
+
const data = await res.json();
|
|
157
|
+
setOrder(data);
|
|
158
|
+
if (data.expectedSenderName) {
|
|
159
|
+
setNameInput(data.expectedSenderName);
|
|
160
|
+
setNameConfirmed(true);
|
|
161
|
+
}
|
|
162
|
+
if (!TERMINAL.includes(data.status)) startPolling();
|
|
163
|
+
}
|
|
164
|
+
function startPolling() {
|
|
165
|
+
pollRef.current = setInterval(async () => {
|
|
166
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
|
|
167
|
+
if (!res.ok) return;
|
|
168
|
+
const data = await res.json();
|
|
169
|
+
setOrder(data);
|
|
170
|
+
if (TERMINAL.includes(data.status)) {
|
|
171
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
172
|
+
handleTerminal(data);
|
|
173
|
+
}
|
|
174
|
+
}, 3e3);
|
|
175
|
+
}
|
|
176
|
+
function handleTerminal(data) {
|
|
177
|
+
if (data.status === "VERIFIED" || data.status === "RESOLVED") {
|
|
178
|
+
onSuccess?.({ orderId: data.id, status: data.status, amount: data.amount });
|
|
179
|
+
} else if (data.status === "EXPIRED") {
|
|
180
|
+
onExpired?.(data.id);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function confirmName() {
|
|
184
|
+
const name = nameInput.trim();
|
|
185
|
+
if (name.length < 2) {
|
|
186
|
+
setNameError("Enter at least 2 characters.");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
setSavingName(true);
|
|
190
|
+
setNameError(null);
|
|
191
|
+
try {
|
|
192
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {
|
|
193
|
+
method: "POST",
|
|
194
|
+
headers: { "Content-Type": "application/json" },
|
|
195
|
+
body: JSON.stringify({ expectedSenderName: name })
|
|
196
|
+
});
|
|
197
|
+
if (!res.ok) throw new Error("Failed");
|
|
198
|
+
setNameConfirmed(true);
|
|
199
|
+
} catch {
|
|
200
|
+
setNameError("Could not save name. Please try again.");
|
|
201
|
+
} finally {
|
|
202
|
+
setSavingName(false);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!open) return null;
|
|
206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.card, children: [
|
|
207
|
+
!order ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { color: "#9ca3af" }, children: "Loading\u2026" }) : order.status === "VERIFIED" || order.status === "RESOLVED" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
208
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u2705" }),
|
|
209
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 700, fontSize: 18, color: "#16a34a", margin: "0 0 4px" }, children: "Payment Verified!" }),
|
|
210
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { fontSize: 26, fontWeight: 700, color: "#111", margin: 0 }, children: [
|
|
211
|
+
"\u20B9",
|
|
212
|
+
(order.amount / 100).toFixed(2)
|
|
213
|
+
] })
|
|
214
|
+
] }) : order.status === "EXPIRED" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
215
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u23F0" }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 600, fontSize: 18, color: "#dc2626" }, children: "Link Expired" })
|
|
217
|
+
] }) : !nameConfirmed ? (
|
|
218
|
+
/* ── Step 1: Name gate ── */
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
220
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.amountBox, children: [
|
|
221
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.amountLabel, children: "Amount" }),
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: baseStyles.amount, children: [
|
|
223
|
+
"\u20B9",
|
|
224
|
+
(order.amount / 100).toFixed(2)
|
|
225
|
+
] })
|
|
226
|
+
] }),
|
|
227
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 700, fontSize: 15, textAlign: "left", marginBottom: 6 }, children: "Enter your name" }),
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.hint, children: "Enter your name exactly as shown in your UPI app. This is used to instantly match your payment." }),
|
|
229
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
230
|
+
"input",
|
|
231
|
+
{
|
|
232
|
+
style: { ...baseStyles.input, ...nameError ? baseStyles.inputError : {} },
|
|
233
|
+
value: nameInput,
|
|
234
|
+
onChange: (e) => {
|
|
235
|
+
setNameInput(e.target.value);
|
|
236
|
+
setNameError(null);
|
|
237
|
+
},
|
|
238
|
+
onKeyDown: (e) => e.key === "Enter" && confirmName(),
|
|
239
|
+
placeholder: "e.g. Rahul Sharma",
|
|
240
|
+
autoFocus: true
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
nameError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.errorText, children: nameError }),
|
|
244
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
245
|
+
"button",
|
|
246
|
+
{
|
|
247
|
+
style: { ...baseStyles.btnPrimary, ...savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {} },
|
|
248
|
+
onClick: confirmName,
|
|
249
|
+
disabled: savingName || nameInput.trim().length < 2,
|
|
250
|
+
children: savingName ? "Saving\u2026" : "Continue \u2192"
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.stepDots, children: [
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(true) }),
|
|
255
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(false) })
|
|
256
|
+
] })
|
|
257
|
+
] })
|
|
258
|
+
) : (
|
|
259
|
+
/* ── Step 2: QR + Pay ── */
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.amountBox, children: [
|
|
262
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.amountLabel, children: "Amount" }),
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: baseStyles.amount, children: [
|
|
264
|
+
"\u20B9",
|
|
265
|
+
(order.amount / 100).toFixed(2)
|
|
266
|
+
] })
|
|
267
|
+
] }),
|
|
268
|
+
order.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 14, color: "#4b5563", marginBottom: 12 }, children: order.description }),
|
|
269
|
+
order.qrCode && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: order.qrCode, width: 200, height: 200, style: { borderRadius: 8, marginBottom: 14 }, alt: "UPI QR" }),
|
|
270
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
271
|
+
"a",
|
|
272
|
+
{
|
|
273
|
+
href: order.upiUri,
|
|
274
|
+
style: {
|
|
275
|
+
display: "flex",
|
|
276
|
+
alignItems: "center",
|
|
277
|
+
justifyContent: "center",
|
|
278
|
+
gap: 8,
|
|
279
|
+
background: "#16a34a",
|
|
280
|
+
color: "white",
|
|
281
|
+
padding: "12px 0",
|
|
282
|
+
borderRadius: 12,
|
|
283
|
+
textDecoration: "none",
|
|
284
|
+
fontWeight: 600,
|
|
285
|
+
fontSize: 15,
|
|
286
|
+
marginBottom: 10
|
|
287
|
+
},
|
|
288
|
+
children: "Open UPI App"
|
|
289
|
+
}
|
|
290
|
+
),
|
|
291
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 12, color: "#9ca3af", marginBottom: 2 }, children: "\u23F3 Waiting for payment\u2026" }),
|
|
292
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.stepDots, children: [
|
|
293
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(false) }),
|
|
294
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(true) })
|
|
295
|
+
] })
|
|
296
|
+
] })
|
|
297
|
+
),
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { style: baseStyles.closeBtn, onClick: onClose, children: "Close" })
|
|
299
|
+
] }) });
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/PaymentButton.tsx
|
|
303
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
304
|
+
function PaymentButton({
|
|
305
|
+
amount,
|
|
306
|
+
description,
|
|
307
|
+
customerEmail,
|
|
308
|
+
customerPhone,
|
|
309
|
+
expectedSenderName,
|
|
310
|
+
metadata,
|
|
311
|
+
onSuccess,
|
|
312
|
+
onExpired,
|
|
313
|
+
className = "",
|
|
314
|
+
children = "Pay Now"
|
|
315
|
+
}) {
|
|
316
|
+
const client = useSeedhaPe();
|
|
317
|
+
const [orderId, setOrderId] = (0, import_react3.useState)(null);
|
|
318
|
+
const [loading, setLoading] = (0, import_react3.useState)(false);
|
|
319
|
+
async function handleClick() {
|
|
320
|
+
setLoading(true);
|
|
321
|
+
try {
|
|
322
|
+
const opts = { amount };
|
|
323
|
+
if (description) opts.description = description;
|
|
324
|
+
if (customerEmail) opts.customerEmail = customerEmail;
|
|
325
|
+
if (customerPhone) opts.customerPhone = customerPhone;
|
|
326
|
+
if (expectedSenderName) opts.expectedSenderName = expectedSenderName;
|
|
327
|
+
if (metadata) opts.metadata = metadata;
|
|
328
|
+
const order = await client.createOrder(opts);
|
|
329
|
+
setOrderId(order.id);
|
|
330
|
+
} catch (err) {
|
|
331
|
+
console.error("[SeedhaPe] Failed to create order:", err);
|
|
332
|
+
} finally {
|
|
333
|
+
setLoading(false);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
337
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
338
|
+
"button",
|
|
339
|
+
{
|
|
340
|
+
onClick: handleClick,
|
|
341
|
+
disabled: loading,
|
|
342
|
+
className: className || "sp-pay-btn",
|
|
343
|
+
style: !className ? {
|
|
344
|
+
background: "#16a34a",
|
|
345
|
+
color: "white",
|
|
346
|
+
border: "none",
|
|
347
|
+
padding: "12px 24px",
|
|
348
|
+
borderRadius: "10px",
|
|
349
|
+
fontWeight: 600,
|
|
350
|
+
fontSize: "15px",
|
|
351
|
+
cursor: loading ? "not-allowed" : "pointer",
|
|
352
|
+
opacity: loading ? 0.7 : 1
|
|
353
|
+
} : void 0,
|
|
354
|
+
children: loading ? "Loading..." : children
|
|
355
|
+
}
|
|
356
|
+
),
|
|
357
|
+
orderId && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
358
|
+
PaymentModal,
|
|
359
|
+
{
|
|
360
|
+
orderId,
|
|
361
|
+
open: true,
|
|
362
|
+
onClose: () => setOrderId(null),
|
|
363
|
+
onSuccess: (result) => {
|
|
364
|
+
setOrderId(null);
|
|
365
|
+
onSuccess?.(result);
|
|
366
|
+
},
|
|
367
|
+
onExpired: (id) => {
|
|
368
|
+
setOrderId(null);
|
|
369
|
+
onExpired?.(id);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
] });
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/usePayment.ts
|
|
377
|
+
var import_react4 = require("react");
|
|
378
|
+
function usePayment() {
|
|
379
|
+
const client = useSeedhaPe();
|
|
380
|
+
const [state, setState] = (0, import_react4.useState)({ phase: "idle" });
|
|
381
|
+
const createPayment = (0, import_react4.useCallback)(
|
|
382
|
+
async (options) => {
|
|
383
|
+
setState({ phase: "creating" });
|
|
384
|
+
try {
|
|
385
|
+
const order = await client.createOrder(options);
|
|
386
|
+
setState({ phase: "pending", order });
|
|
387
|
+
return order;
|
|
388
|
+
} catch (err) {
|
|
389
|
+
setState({ phase: "error", error: String(err) });
|
|
390
|
+
throw err;
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
[client]
|
|
394
|
+
);
|
|
395
|
+
const onSuccess = (0, import_react4.useCallback)((result) => {
|
|
396
|
+
setState({ phase: "verified", result });
|
|
397
|
+
}, []);
|
|
398
|
+
const onExpired = (0, import_react4.useCallback)((orderId) => {
|
|
399
|
+
setState({ phase: "expired", orderId });
|
|
400
|
+
}, []);
|
|
401
|
+
const reset = (0, import_react4.useCallback)(() => setState({ phase: "idle" }), []);
|
|
402
|
+
return { state, createPayment, onSuccess, onExpired, reset };
|
|
403
|
+
}
|
|
404
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
405
|
+
0 && (module.exports = {
|
|
406
|
+
PaymentButton,
|
|
407
|
+
PaymentModal,
|
|
408
|
+
SeedhaPeProvider,
|
|
409
|
+
usePayment,
|
|
410
|
+
useSeedhaPe
|
|
411
|
+
});
|
|
412
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/PaymentButton.tsx","../src/PaymentModal.tsx","../src/usePayment.ts"],"sourcesContent":["export { SeedhaPeProvider, useSeedhaPe } from './provider.js';\nexport { PaymentButton } from './PaymentButton.js';\nexport { PaymentModal } from './PaymentModal.js';\nexport { usePayment } from './usePayment.js';\nexport type { PaymentButtonProps, PaymentModalProps } from './types.js';\n","import React, { createContext, useContext, useMemo } from 'react';\nimport { SeedhaPe } from '@seedhape/sdk';\n\ninterface SeedhaPeContextValue {\n client: SeedhaPe;\n}\n\nconst SeedhaPeContext = createContext<SeedhaPeContextValue | null>(null);\n\nexport function SeedhaPeProvider({\n apiKey,\n baseUrl,\n children,\n}: {\n apiKey: string;\n baseUrl?: string;\n children: React.ReactNode;\n}) {\n const client = useMemo(() => {\n const config: import('@seedhape/sdk').SeedhaPeConfig = { apiKey };\n if (baseUrl) config.baseUrl = baseUrl;\n return new SeedhaPe(config);\n }, [apiKey, baseUrl]);\n\n return (\n <SeedhaPeContext.Provider value={{ client }}>\n {children}\n </SeedhaPeContext.Provider>\n );\n}\n\nexport function useSeedhaPe(): SeedhaPe {\n const ctx = useContext(SeedhaPeContext);\n if (!ctx) throw new Error('useSeedhaPe must be used inside <SeedhaPeProvider>');\n return ctx.client;\n}\n","import React, { useState } from 'react';\nimport type { PaymentButtonProps } from './types.js';\nimport { PaymentModal } from './PaymentModal.js';\nimport { useSeedhaPe } from './provider.js';\n\nexport function PaymentButton({\n amount,\n description,\n customerEmail,\n customerPhone,\n expectedSenderName,\n metadata,\n onSuccess,\n onExpired,\n className = '',\n children = 'Pay Now',\n}: PaymentButtonProps) {\n const client = useSeedhaPe();\n const [orderId, setOrderId] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function handleClick() {\n setLoading(true);\n try {\n const opts: import('@seedhape/sdk').CreateOrderOptions = { amount };\n if (description) opts.description = description;\n if (customerEmail) opts.customerEmail = customerEmail;\n if (customerPhone) opts.customerPhone = customerPhone;\n if (expectedSenderName) opts.expectedSenderName = expectedSenderName;\n if (metadata) opts.metadata = metadata;\n const order = await client.createOrder(opts);\n setOrderId(order.id);\n } catch (err) {\n console.error('[SeedhaPe] Failed to create order:', err);\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <button\n onClick={handleClick}\n disabled={loading}\n className={className || 'sp-pay-btn'}\n style={\n !className\n ? {\n background: '#16a34a',\n color: 'white',\n border: 'none',\n padding: '12px 24px',\n borderRadius: '10px',\n fontWeight: 600,\n fontSize: '15px',\n cursor: loading ? 'not-allowed' : 'pointer',\n opacity: loading ? 0.7 : 1,\n }\n : undefined\n }\n >\n {loading ? 'Loading...' : children}\n </button>\n\n {orderId && (\n <PaymentModal\n orderId={orderId}\n open={true}\n onClose={() => setOrderId(null)}\n onSuccess={(result) => {\n setOrderId(null);\n onSuccess?.(result);\n }}\n onExpired={(id) => {\n setOrderId(null);\n onExpired?.(id);\n }}\n />\n )}\n </>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { PaymentModalProps } from './types.js';\n\n// API URL can be set via __SEEDHAPE_API_URL__ global, or defaults to production\ndeclare const __SEEDHAPE_API_URL__: string | undefined;\nconst API_URL: string =\n typeof __SEEDHAPE_API_URL__ !== 'undefined'\n ? __SEEDHAPE_API_URL__\n : 'https://api.seedhape.com';\n\ntype OrderData = {\n id: string;\n amount: number;\n description: string | null;\n status: string;\n upiUri: string;\n qrCode: string;\n expiresAt: string;\n expectedSenderName: string | null;\n};\n\nconst TERMINAL = ['VERIFIED', 'RESOLVED', 'EXPIRED', 'REJECTED'];\n\nconst baseStyles = {\n overlay: {\n position: 'fixed' as const, inset: 0,\n background: 'rgba(0,0,0,0.5)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n zIndex: 99999, fontFamily: 'system-ui, sans-serif',\n },\n card: {\n background: 'white', borderRadius: 16, padding: 28,\n width: 360, maxWidth: 'calc(100vw - 32px)', textAlign: 'center' as const,\n boxShadow: '0 25px 50px rgba(0,0,0,0.2)',\n },\n amountBox: {\n background: '#f0fdf4', borderRadius: 12, padding: '12px 16px',\n marginBottom: 20,\n },\n amountLabel: { fontSize: 12, color: '#15803d', marginBottom: 2 },\n amount: { fontSize: 28, fontWeight: 700, color: '#14532d', margin: 0 },\n input: {\n width: '100%', border: '1.5px solid #d1d5db', borderRadius: 10,\n padding: '10px 12px', fontSize: 14, boxSizing: 'border-box' as const,\n outline: 'none', marginBottom: 8,\n },\n inputError: { borderColor: '#f87171' },\n btnPrimary: {\n width: '100%', background: '#16a34a', color: 'white', border: 'none',\n borderRadius: 12, padding: '12px 0', fontSize: 15, fontWeight: 600,\n cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n },\n btnDisabled: { opacity: 0.5, cursor: 'not-allowed' as const },\n closeBtn: {\n marginTop: 14, background: 'none', border: 'none',\n color: '#9ca3af', fontSize: 13, cursor: 'pointer',\n },\n hint: { fontSize: 12, color: '#6b7280', lineHeight: 1.5, marginBottom: 12, textAlign: 'left' as const },\n errorText: { fontSize: 12, color: '#ef4444', marginBottom: 8, textAlign: 'left' as const },\n stepDots: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 14 },\n dot: (active: boolean) => ({\n width: 24, height: 6, borderRadius: 3,\n background: active ? '#16a34a' : '#e5e7eb',\n }),\n};\n\nexport function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps) {\n const [order, setOrder] = useState<OrderData | null>(null);\n const [nameInput, setNameInput] = useState('');\n const [nameError, setNameError] = useState<string | null>(null);\n const [savingName, setSavingName] = useState(false);\n const [nameConfirmed, setNameConfirmed] = useState(false);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!open || !orderId) return;\n setOrder(null);\n setNameInput('');\n setNameError(null);\n setNameConfirmed(false);\n fetchOrder();\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [open, orderId]);\n\n async function fetchOrder() {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n // Skip name gate if the merchant already supplied it at order creation time\n if (data.expectedSenderName) {\n setNameInput(data.expectedSenderName);\n setNameConfirmed(true);\n }\n if (!TERMINAL.includes(data.status)) startPolling();\n }\n\n function startPolling() {\n pollRef.current = setInterval(async () => {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n if (TERMINAL.includes(data.status)) {\n if (pollRef.current) clearInterval(pollRef.current);\n handleTerminal(data);\n }\n }, 3000);\n }\n\n function handleTerminal(data: OrderData) {\n if (data.status === 'VERIFIED' || data.status === 'RESOLVED') {\n onSuccess?.({ orderId: data.id, status: data.status as 'VERIFIED', amount: data.amount });\n } else if (data.status === 'EXPIRED') {\n onExpired?.(data.id);\n }\n }\n\n async function confirmName() {\n const name = nameInput.trim();\n if (name.length < 2) { setNameError('Enter at least 2 characters.'); return; }\n setSavingName(true);\n setNameError(null);\n try {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ expectedSenderName: name }),\n });\n if (!res.ok) throw new Error('Failed');\n setNameConfirmed(true);\n } catch {\n setNameError('Could not save name. Please try again.');\n } finally {\n setSavingName(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div style={baseStyles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>\n <div style={baseStyles.card}>\n {!order ? (\n <p style={{ color: '#9ca3af' }}>Loading…</p>\n ) : (order.status === 'VERIFIED' || order.status === 'RESOLVED') ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>✅</div>\n <p style={{ fontWeight: 700, fontSize: 18, color: '#16a34a', margin: '0 0 4px' }}>Payment Verified!</p>\n <p style={{ fontSize: 26, fontWeight: 700, color: '#111', margin: 0 }}>\n ₹{(order.amount / 100).toFixed(2)}\n </p>\n </>\n ) : order.status === 'EXPIRED' ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>⏰</div>\n <p style={{ fontWeight: 600, fontSize: 18, color: '#dc2626' }}>Link Expired</p>\n </>\n ) : !nameConfirmed ? (\n /* ── Step 1: Name gate ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n <p style={{ fontWeight: 700, fontSize: 15, textAlign: 'left', marginBottom: 6 }}>Enter your name</p>\n <p style={baseStyles.hint}>\n Enter your name exactly as shown in your UPI app. This is used to instantly match your payment.\n </p>\n <input\n style={{ ...baseStyles.input, ...(nameError ? baseStyles.inputError : {}) }}\n value={nameInput}\n onChange={(e) => { setNameInput(e.target.value); setNameError(null); }}\n onKeyDown={(e) => e.key === 'Enter' && confirmName()}\n placeholder=\"e.g. Rahul Sharma\"\n autoFocus\n />\n {nameError && <p style={baseStyles.errorText}>{nameError}</p>}\n <button\n style={{ ...baseStyles.btnPrimary, ...(savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {}) }}\n onClick={confirmName}\n disabled={savingName || nameInput.trim().length < 2}\n >\n {savingName ? 'Saving…' : 'Continue →'}\n </button>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(true)} />\n <div style={baseStyles.dot(false)} />\n </div>\n </>\n ) : (\n /* ── Step 2: QR + Pay ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n {order.description && (\n <p style={{ fontSize: 14, color: '#4b5563', marginBottom: 12 }}>{order.description}</p>\n )}\n {order.qrCode && (\n <img src={order.qrCode} width={200} height={200} style={{ borderRadius: 8, marginBottom: 14 }} alt=\"UPI QR\" />\n )}\n <a\n href={order.upiUri}\n style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n background: '#16a34a', color: 'white',\n padding: '12px 0', borderRadius: 12, textDecoration: 'none',\n fontWeight: 600, fontSize: 15, marginBottom: 10,\n }}\n >\n Open UPI App\n </a>\n <p style={{ fontSize: 12, color: '#9ca3af', marginBottom: 2 }}>⏳ Waiting for payment…</p>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(false)} />\n <div style={baseStyles.dot(true)} />\n </div>\n </>\n )}\n\n <button style={baseStyles.closeBtn} onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport type { OrderData, PaymentResult } from '@seedhape/sdk';\n\nimport { useSeedhaPe } from './provider.js';\n\ntype PaymentState =\n | { phase: 'idle' }\n | { phase: 'creating' }\n | { phase: 'pending'; order: OrderData }\n | { phase: 'verified'; result: PaymentResult }\n | { phase: 'expired'; orderId: string }\n | { phase: 'error'; error: string };\n\nexport function usePayment() {\n const client = useSeedhaPe();\n const [state, setState] = useState<PaymentState>({ phase: 'idle' });\n\n const createPayment = useCallback(\n async (options: {\n amount: number;\n description?: string;\n customerEmail?: string;\n customerPhone?: string;\n metadata?: Record<string, unknown>;\n }) => {\n setState({ phase: 'creating' });\n try {\n const order = await client.createOrder(options);\n setState({ phase: 'pending', order });\n return order;\n } catch (err) {\n setState({ phase: 'error', error: String(err) });\n throw err;\n }\n },\n [client],\n );\n\n const onSuccess = useCallback((result: PaymentResult) => {\n setState({ phase: 'verified', result });\n }, []);\n\n const onExpired = useCallback((orderId: string) => {\n setState({ phase: 'expired', orderId });\n }, []);\n\n const reset = useCallback(() => setState({ phase: 'idle' }), []);\n\n return { state, createPayment, onSuccess, onExpired, reset };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
3
|
+
import { SeedhaPe, PaymentResult, OrderData } from '@seedhape/sdk';
|
|
4
|
+
|
|
5
|
+
declare function SeedhaPeProvider({ apiKey, baseUrl, children, }: {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
children: React$1.ReactNode;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare function useSeedhaPe(): SeedhaPe;
|
|
11
|
+
|
|
12
|
+
interface PaymentButtonProps {
|
|
13
|
+
amount: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
customerEmail?: string;
|
|
16
|
+
customerPhone?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The payer's name exactly as it appears in their UPI app.
|
|
19
|
+
* Strongly recommended — improves payment matching accuracy.
|
|
20
|
+
* When omitted the modal will prompt the user to enter it before showing the QR code.
|
|
21
|
+
*/
|
|
22
|
+
expectedSenderName?: string;
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
onSuccess?: (result: PaymentResult) => void;
|
|
25
|
+
onExpired?: (orderId: string) => void;
|
|
26
|
+
className?: string;
|
|
27
|
+
children?: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
interface PaymentModalProps {
|
|
30
|
+
orderId: string;
|
|
31
|
+
open: boolean;
|
|
32
|
+
onClose: () => void;
|
|
33
|
+
onSuccess?: (result: PaymentResult) => void;
|
|
34
|
+
onExpired?: (orderId: string) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare function PaymentButton({ amount, description, customerEmail, customerPhone, expectedSenderName, metadata, onSuccess, onExpired, className, children, }: PaymentButtonProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
|
|
39
|
+
declare function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps): react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
|
|
41
|
+
type PaymentState = {
|
|
42
|
+
phase: 'idle';
|
|
43
|
+
} | {
|
|
44
|
+
phase: 'creating';
|
|
45
|
+
} | {
|
|
46
|
+
phase: 'pending';
|
|
47
|
+
order: OrderData;
|
|
48
|
+
} | {
|
|
49
|
+
phase: 'verified';
|
|
50
|
+
result: PaymentResult;
|
|
51
|
+
} | {
|
|
52
|
+
phase: 'expired';
|
|
53
|
+
orderId: string;
|
|
54
|
+
} | {
|
|
55
|
+
phase: 'error';
|
|
56
|
+
error: string;
|
|
57
|
+
};
|
|
58
|
+
declare function usePayment(): {
|
|
59
|
+
state: PaymentState;
|
|
60
|
+
createPayment: (options: {
|
|
61
|
+
amount: number;
|
|
62
|
+
description?: string;
|
|
63
|
+
customerEmail?: string;
|
|
64
|
+
customerPhone?: string;
|
|
65
|
+
metadata?: Record<string, unknown>;
|
|
66
|
+
}) => Promise<OrderData>;
|
|
67
|
+
onSuccess: (result: PaymentResult) => void;
|
|
68
|
+
onExpired: (orderId: string) => void;
|
|
69
|
+
reset: () => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { PaymentButton, type PaymentButtonProps, PaymentModal, type PaymentModalProps, SeedhaPeProvider, usePayment, useSeedhaPe };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
3
|
+
import { SeedhaPe, PaymentResult, OrderData } from '@seedhape/sdk';
|
|
4
|
+
|
|
5
|
+
declare function SeedhaPeProvider({ apiKey, baseUrl, children, }: {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
children: React$1.ReactNode;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare function useSeedhaPe(): SeedhaPe;
|
|
11
|
+
|
|
12
|
+
interface PaymentButtonProps {
|
|
13
|
+
amount: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
customerEmail?: string;
|
|
16
|
+
customerPhone?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The payer's name exactly as it appears in their UPI app.
|
|
19
|
+
* Strongly recommended — improves payment matching accuracy.
|
|
20
|
+
* When omitted the modal will prompt the user to enter it before showing the QR code.
|
|
21
|
+
*/
|
|
22
|
+
expectedSenderName?: string;
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
onSuccess?: (result: PaymentResult) => void;
|
|
25
|
+
onExpired?: (orderId: string) => void;
|
|
26
|
+
className?: string;
|
|
27
|
+
children?: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
interface PaymentModalProps {
|
|
30
|
+
orderId: string;
|
|
31
|
+
open: boolean;
|
|
32
|
+
onClose: () => void;
|
|
33
|
+
onSuccess?: (result: PaymentResult) => void;
|
|
34
|
+
onExpired?: (orderId: string) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
declare function PaymentButton({ amount, description, customerEmail, customerPhone, expectedSenderName, metadata, onSuccess, onExpired, className, children, }: PaymentButtonProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
|
|
39
|
+
declare function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps): react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
|
|
41
|
+
type PaymentState = {
|
|
42
|
+
phase: 'idle';
|
|
43
|
+
} | {
|
|
44
|
+
phase: 'creating';
|
|
45
|
+
} | {
|
|
46
|
+
phase: 'pending';
|
|
47
|
+
order: OrderData;
|
|
48
|
+
} | {
|
|
49
|
+
phase: 'verified';
|
|
50
|
+
result: PaymentResult;
|
|
51
|
+
} | {
|
|
52
|
+
phase: 'expired';
|
|
53
|
+
orderId: string;
|
|
54
|
+
} | {
|
|
55
|
+
phase: 'error';
|
|
56
|
+
error: string;
|
|
57
|
+
};
|
|
58
|
+
declare function usePayment(): {
|
|
59
|
+
state: PaymentState;
|
|
60
|
+
createPayment: (options: {
|
|
61
|
+
amount: number;
|
|
62
|
+
description?: string;
|
|
63
|
+
customerEmail?: string;
|
|
64
|
+
customerPhone?: string;
|
|
65
|
+
metadata?: Record<string, unknown>;
|
|
66
|
+
}) => Promise<OrderData>;
|
|
67
|
+
onSuccess: (result: PaymentResult) => void;
|
|
68
|
+
onExpired: (orderId: string) => void;
|
|
69
|
+
reset: () => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { PaymentButton, type PaymentButtonProps, PaymentModal, type PaymentModalProps, SeedhaPeProvider, usePayment, useSeedhaPe };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// src/provider.tsx
|
|
2
|
+
import { createContext, useContext, useMemo } from "react";
|
|
3
|
+
import { SeedhaPe } from "@seedhape/sdk";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
var SeedhaPeContext = createContext(null);
|
|
6
|
+
function SeedhaPeProvider({
|
|
7
|
+
apiKey,
|
|
8
|
+
baseUrl,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
const client = useMemo(() => {
|
|
12
|
+
const config = { apiKey };
|
|
13
|
+
if (baseUrl) config.baseUrl = baseUrl;
|
|
14
|
+
return new SeedhaPe(config);
|
|
15
|
+
}, [apiKey, baseUrl]);
|
|
16
|
+
return /* @__PURE__ */ jsx(SeedhaPeContext.Provider, { value: { client }, children });
|
|
17
|
+
}
|
|
18
|
+
function useSeedhaPe() {
|
|
19
|
+
const ctx = useContext(SeedhaPeContext);
|
|
20
|
+
if (!ctx) throw new Error("useSeedhaPe must be used inside <SeedhaPeProvider>");
|
|
21
|
+
return ctx.client;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/PaymentButton.tsx
|
|
25
|
+
import { useState as useState2 } from "react";
|
|
26
|
+
|
|
27
|
+
// src/PaymentModal.tsx
|
|
28
|
+
import { useEffect, useRef, useState } from "react";
|
|
29
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
30
|
+
var API_URL = typeof __SEEDHAPE_API_URL__ !== "undefined" ? __SEEDHAPE_API_URL__ : "https://api.seedhape.com";
|
|
31
|
+
var TERMINAL = ["VERIFIED", "RESOLVED", "EXPIRED", "REJECTED"];
|
|
32
|
+
var baseStyles = {
|
|
33
|
+
overlay: {
|
|
34
|
+
position: "fixed",
|
|
35
|
+
inset: 0,
|
|
36
|
+
background: "rgba(0,0,0,0.5)",
|
|
37
|
+
display: "flex",
|
|
38
|
+
alignItems: "center",
|
|
39
|
+
justifyContent: "center",
|
|
40
|
+
zIndex: 99999,
|
|
41
|
+
fontFamily: "system-ui, sans-serif"
|
|
42
|
+
},
|
|
43
|
+
card: {
|
|
44
|
+
background: "white",
|
|
45
|
+
borderRadius: 16,
|
|
46
|
+
padding: 28,
|
|
47
|
+
width: 360,
|
|
48
|
+
maxWidth: "calc(100vw - 32px)",
|
|
49
|
+
textAlign: "center",
|
|
50
|
+
boxShadow: "0 25px 50px rgba(0,0,0,0.2)"
|
|
51
|
+
},
|
|
52
|
+
amountBox: {
|
|
53
|
+
background: "#f0fdf4",
|
|
54
|
+
borderRadius: 12,
|
|
55
|
+
padding: "12px 16px",
|
|
56
|
+
marginBottom: 20
|
|
57
|
+
},
|
|
58
|
+
amountLabel: { fontSize: 12, color: "#15803d", marginBottom: 2 },
|
|
59
|
+
amount: { fontSize: 28, fontWeight: 700, color: "#14532d", margin: 0 },
|
|
60
|
+
input: {
|
|
61
|
+
width: "100%",
|
|
62
|
+
border: "1.5px solid #d1d5db",
|
|
63
|
+
borderRadius: 10,
|
|
64
|
+
padding: "10px 12px",
|
|
65
|
+
fontSize: 14,
|
|
66
|
+
boxSizing: "border-box",
|
|
67
|
+
outline: "none",
|
|
68
|
+
marginBottom: 8
|
|
69
|
+
},
|
|
70
|
+
inputError: { borderColor: "#f87171" },
|
|
71
|
+
btnPrimary: {
|
|
72
|
+
width: "100%",
|
|
73
|
+
background: "#16a34a",
|
|
74
|
+
color: "white",
|
|
75
|
+
border: "none",
|
|
76
|
+
borderRadius: 12,
|
|
77
|
+
padding: "12px 0",
|
|
78
|
+
fontSize: 15,
|
|
79
|
+
fontWeight: 600,
|
|
80
|
+
cursor: "pointer",
|
|
81
|
+
display: "flex",
|
|
82
|
+
alignItems: "center",
|
|
83
|
+
justifyContent: "center",
|
|
84
|
+
gap: 8
|
|
85
|
+
},
|
|
86
|
+
btnDisabled: { opacity: 0.5, cursor: "not-allowed" },
|
|
87
|
+
closeBtn: {
|
|
88
|
+
marginTop: 14,
|
|
89
|
+
background: "none",
|
|
90
|
+
border: "none",
|
|
91
|
+
color: "#9ca3af",
|
|
92
|
+
fontSize: 13,
|
|
93
|
+
cursor: "pointer"
|
|
94
|
+
},
|
|
95
|
+
hint: { fontSize: 12, color: "#6b7280", lineHeight: 1.5, marginBottom: 12, textAlign: "left" },
|
|
96
|
+
errorText: { fontSize: 12, color: "#ef4444", marginBottom: 8, textAlign: "left" },
|
|
97
|
+
stepDots: { display: "flex", justifyContent: "center", gap: 6, marginTop: 14 },
|
|
98
|
+
dot: (active) => ({
|
|
99
|
+
width: 24,
|
|
100
|
+
height: 6,
|
|
101
|
+
borderRadius: 3,
|
|
102
|
+
background: active ? "#16a34a" : "#e5e7eb"
|
|
103
|
+
})
|
|
104
|
+
};
|
|
105
|
+
function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }) {
|
|
106
|
+
const [order, setOrder] = useState(null);
|
|
107
|
+
const [nameInput, setNameInput] = useState("");
|
|
108
|
+
const [nameError, setNameError] = useState(null);
|
|
109
|
+
const [savingName, setSavingName] = useState(false);
|
|
110
|
+
const [nameConfirmed, setNameConfirmed] = useState(false);
|
|
111
|
+
const pollRef = useRef(null);
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (!open || !orderId) return;
|
|
114
|
+
setOrder(null);
|
|
115
|
+
setNameInput("");
|
|
116
|
+
setNameError(null);
|
|
117
|
+
setNameConfirmed(false);
|
|
118
|
+
fetchOrder();
|
|
119
|
+
return () => {
|
|
120
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
121
|
+
};
|
|
122
|
+
}, [open, orderId]);
|
|
123
|
+
async function fetchOrder() {
|
|
124
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
|
|
125
|
+
if (!res.ok) return;
|
|
126
|
+
const data = await res.json();
|
|
127
|
+
setOrder(data);
|
|
128
|
+
if (data.expectedSenderName) {
|
|
129
|
+
setNameInput(data.expectedSenderName);
|
|
130
|
+
setNameConfirmed(true);
|
|
131
|
+
}
|
|
132
|
+
if (!TERMINAL.includes(data.status)) startPolling();
|
|
133
|
+
}
|
|
134
|
+
function startPolling() {
|
|
135
|
+
pollRef.current = setInterval(async () => {
|
|
136
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
|
|
137
|
+
if (!res.ok) return;
|
|
138
|
+
const data = await res.json();
|
|
139
|
+
setOrder(data);
|
|
140
|
+
if (TERMINAL.includes(data.status)) {
|
|
141
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
142
|
+
handleTerminal(data);
|
|
143
|
+
}
|
|
144
|
+
}, 3e3);
|
|
145
|
+
}
|
|
146
|
+
function handleTerminal(data) {
|
|
147
|
+
if (data.status === "VERIFIED" || data.status === "RESOLVED") {
|
|
148
|
+
onSuccess?.({ orderId: data.id, status: data.status, amount: data.amount });
|
|
149
|
+
} else if (data.status === "EXPIRED") {
|
|
150
|
+
onExpired?.(data.id);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function confirmName() {
|
|
154
|
+
const name = nameInput.trim();
|
|
155
|
+
if (name.length < 2) {
|
|
156
|
+
setNameError("Enter at least 2 characters.");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
setSavingName(true);
|
|
160
|
+
setNameError(null);
|
|
161
|
+
try {
|
|
162
|
+
const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {
|
|
163
|
+
method: "POST",
|
|
164
|
+
headers: { "Content-Type": "application/json" },
|
|
165
|
+
body: JSON.stringify({ expectedSenderName: name })
|
|
166
|
+
});
|
|
167
|
+
if (!res.ok) throw new Error("Failed");
|
|
168
|
+
setNameConfirmed(true);
|
|
169
|
+
} catch {
|
|
170
|
+
setNameError("Could not save name. Please try again.");
|
|
171
|
+
} finally {
|
|
172
|
+
setSavingName(false);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!open) return null;
|
|
176
|
+
return /* @__PURE__ */ jsx2("div", { style: baseStyles.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ jsxs("div", { style: baseStyles.card, children: [
|
|
177
|
+
!order ? /* @__PURE__ */ jsx2("p", { style: { color: "#9ca3af" }, children: "Loading\u2026" }) : order.status === "VERIFIED" || order.status === "RESOLVED" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
178
|
+
/* @__PURE__ */ jsx2("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u2705" }),
|
|
179
|
+
/* @__PURE__ */ jsx2("p", { style: { fontWeight: 700, fontSize: 18, color: "#16a34a", margin: "0 0 4px" }, children: "Payment Verified!" }),
|
|
180
|
+
/* @__PURE__ */ jsxs("p", { style: { fontSize: 26, fontWeight: 700, color: "#111", margin: 0 }, children: [
|
|
181
|
+
"\u20B9",
|
|
182
|
+
(order.amount / 100).toFixed(2)
|
|
183
|
+
] })
|
|
184
|
+
] }) : order.status === "EXPIRED" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
185
|
+
/* @__PURE__ */ jsx2("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u23F0" }),
|
|
186
|
+
/* @__PURE__ */ jsx2("p", { style: { fontWeight: 600, fontSize: 18, color: "#dc2626" }, children: "Link Expired" })
|
|
187
|
+
] }) : !nameConfirmed ? (
|
|
188
|
+
/* ── Step 1: Name gate ── */
|
|
189
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
|
+
/* @__PURE__ */ jsxs("div", { style: baseStyles.amountBox, children: [
|
|
191
|
+
/* @__PURE__ */ jsx2("p", { style: baseStyles.amountLabel, children: "Amount" }),
|
|
192
|
+
/* @__PURE__ */ jsxs("p", { style: baseStyles.amount, children: [
|
|
193
|
+
"\u20B9",
|
|
194
|
+
(order.amount / 100).toFixed(2)
|
|
195
|
+
] })
|
|
196
|
+
] }),
|
|
197
|
+
/* @__PURE__ */ jsx2("p", { style: { fontWeight: 700, fontSize: 15, textAlign: "left", marginBottom: 6 }, children: "Enter your name" }),
|
|
198
|
+
/* @__PURE__ */ jsx2("p", { style: baseStyles.hint, children: "Enter your name exactly as shown in your UPI app. This is used to instantly match your payment." }),
|
|
199
|
+
/* @__PURE__ */ jsx2(
|
|
200
|
+
"input",
|
|
201
|
+
{
|
|
202
|
+
style: { ...baseStyles.input, ...nameError ? baseStyles.inputError : {} },
|
|
203
|
+
value: nameInput,
|
|
204
|
+
onChange: (e) => {
|
|
205
|
+
setNameInput(e.target.value);
|
|
206
|
+
setNameError(null);
|
|
207
|
+
},
|
|
208
|
+
onKeyDown: (e) => e.key === "Enter" && confirmName(),
|
|
209
|
+
placeholder: "e.g. Rahul Sharma",
|
|
210
|
+
autoFocus: true
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
nameError && /* @__PURE__ */ jsx2("p", { style: baseStyles.errorText, children: nameError }),
|
|
214
|
+
/* @__PURE__ */ jsx2(
|
|
215
|
+
"button",
|
|
216
|
+
{
|
|
217
|
+
style: { ...baseStyles.btnPrimary, ...savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {} },
|
|
218
|
+
onClick: confirmName,
|
|
219
|
+
disabled: savingName || nameInput.trim().length < 2,
|
|
220
|
+
children: savingName ? "Saving\u2026" : "Continue \u2192"
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
/* @__PURE__ */ jsxs("div", { style: baseStyles.stepDots, children: [
|
|
224
|
+
/* @__PURE__ */ jsx2("div", { style: baseStyles.dot(true) }),
|
|
225
|
+
/* @__PURE__ */ jsx2("div", { style: baseStyles.dot(false) })
|
|
226
|
+
] })
|
|
227
|
+
] })
|
|
228
|
+
) : (
|
|
229
|
+
/* ── Step 2: QR + Pay ── */
|
|
230
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
231
|
+
/* @__PURE__ */ jsxs("div", { style: baseStyles.amountBox, children: [
|
|
232
|
+
/* @__PURE__ */ jsx2("p", { style: baseStyles.amountLabel, children: "Amount" }),
|
|
233
|
+
/* @__PURE__ */ jsxs("p", { style: baseStyles.amount, children: [
|
|
234
|
+
"\u20B9",
|
|
235
|
+
(order.amount / 100).toFixed(2)
|
|
236
|
+
] })
|
|
237
|
+
] }),
|
|
238
|
+
order.description && /* @__PURE__ */ jsx2("p", { style: { fontSize: 14, color: "#4b5563", marginBottom: 12 }, children: order.description }),
|
|
239
|
+
order.qrCode && /* @__PURE__ */ jsx2("img", { src: order.qrCode, width: 200, height: 200, style: { borderRadius: 8, marginBottom: 14 }, alt: "UPI QR" }),
|
|
240
|
+
/* @__PURE__ */ jsx2(
|
|
241
|
+
"a",
|
|
242
|
+
{
|
|
243
|
+
href: order.upiUri,
|
|
244
|
+
style: {
|
|
245
|
+
display: "flex",
|
|
246
|
+
alignItems: "center",
|
|
247
|
+
justifyContent: "center",
|
|
248
|
+
gap: 8,
|
|
249
|
+
background: "#16a34a",
|
|
250
|
+
color: "white",
|
|
251
|
+
padding: "12px 0",
|
|
252
|
+
borderRadius: 12,
|
|
253
|
+
textDecoration: "none",
|
|
254
|
+
fontWeight: 600,
|
|
255
|
+
fontSize: 15,
|
|
256
|
+
marginBottom: 10
|
|
257
|
+
},
|
|
258
|
+
children: "Open UPI App"
|
|
259
|
+
}
|
|
260
|
+
),
|
|
261
|
+
/* @__PURE__ */ jsx2("p", { style: { fontSize: 12, color: "#9ca3af", marginBottom: 2 }, children: "\u23F3 Waiting for payment\u2026" }),
|
|
262
|
+
/* @__PURE__ */ jsxs("div", { style: baseStyles.stepDots, children: [
|
|
263
|
+
/* @__PURE__ */ jsx2("div", { style: baseStyles.dot(false) }),
|
|
264
|
+
/* @__PURE__ */ jsx2("div", { style: baseStyles.dot(true) })
|
|
265
|
+
] })
|
|
266
|
+
] })
|
|
267
|
+
),
|
|
268
|
+
/* @__PURE__ */ jsx2("button", { style: baseStyles.closeBtn, onClick: onClose, children: "Close" })
|
|
269
|
+
] }) });
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/PaymentButton.tsx
|
|
273
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
274
|
+
function PaymentButton({
|
|
275
|
+
amount,
|
|
276
|
+
description,
|
|
277
|
+
customerEmail,
|
|
278
|
+
customerPhone,
|
|
279
|
+
expectedSenderName,
|
|
280
|
+
metadata,
|
|
281
|
+
onSuccess,
|
|
282
|
+
onExpired,
|
|
283
|
+
className = "",
|
|
284
|
+
children = "Pay Now"
|
|
285
|
+
}) {
|
|
286
|
+
const client = useSeedhaPe();
|
|
287
|
+
const [orderId, setOrderId] = useState2(null);
|
|
288
|
+
const [loading, setLoading] = useState2(false);
|
|
289
|
+
async function handleClick() {
|
|
290
|
+
setLoading(true);
|
|
291
|
+
try {
|
|
292
|
+
const opts = { amount };
|
|
293
|
+
if (description) opts.description = description;
|
|
294
|
+
if (customerEmail) opts.customerEmail = customerEmail;
|
|
295
|
+
if (customerPhone) opts.customerPhone = customerPhone;
|
|
296
|
+
if (expectedSenderName) opts.expectedSenderName = expectedSenderName;
|
|
297
|
+
if (metadata) opts.metadata = metadata;
|
|
298
|
+
const order = await client.createOrder(opts);
|
|
299
|
+
setOrderId(order.id);
|
|
300
|
+
} catch (err) {
|
|
301
|
+
console.error("[SeedhaPe] Failed to create order:", err);
|
|
302
|
+
} finally {
|
|
303
|
+
setLoading(false);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
307
|
+
/* @__PURE__ */ jsx3(
|
|
308
|
+
"button",
|
|
309
|
+
{
|
|
310
|
+
onClick: handleClick,
|
|
311
|
+
disabled: loading,
|
|
312
|
+
className: className || "sp-pay-btn",
|
|
313
|
+
style: !className ? {
|
|
314
|
+
background: "#16a34a",
|
|
315
|
+
color: "white",
|
|
316
|
+
border: "none",
|
|
317
|
+
padding: "12px 24px",
|
|
318
|
+
borderRadius: "10px",
|
|
319
|
+
fontWeight: 600,
|
|
320
|
+
fontSize: "15px",
|
|
321
|
+
cursor: loading ? "not-allowed" : "pointer",
|
|
322
|
+
opacity: loading ? 0.7 : 1
|
|
323
|
+
} : void 0,
|
|
324
|
+
children: loading ? "Loading..." : children
|
|
325
|
+
}
|
|
326
|
+
),
|
|
327
|
+
orderId && /* @__PURE__ */ jsx3(
|
|
328
|
+
PaymentModal,
|
|
329
|
+
{
|
|
330
|
+
orderId,
|
|
331
|
+
open: true,
|
|
332
|
+
onClose: () => setOrderId(null),
|
|
333
|
+
onSuccess: (result) => {
|
|
334
|
+
setOrderId(null);
|
|
335
|
+
onSuccess?.(result);
|
|
336
|
+
},
|
|
337
|
+
onExpired: (id) => {
|
|
338
|
+
setOrderId(null);
|
|
339
|
+
onExpired?.(id);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
] });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/usePayment.ts
|
|
347
|
+
import { useState as useState3, useCallback } from "react";
|
|
348
|
+
function usePayment() {
|
|
349
|
+
const client = useSeedhaPe();
|
|
350
|
+
const [state, setState] = useState3({ phase: "idle" });
|
|
351
|
+
const createPayment = useCallback(
|
|
352
|
+
async (options) => {
|
|
353
|
+
setState({ phase: "creating" });
|
|
354
|
+
try {
|
|
355
|
+
const order = await client.createOrder(options);
|
|
356
|
+
setState({ phase: "pending", order });
|
|
357
|
+
return order;
|
|
358
|
+
} catch (err) {
|
|
359
|
+
setState({ phase: "error", error: String(err) });
|
|
360
|
+
throw err;
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
[client]
|
|
364
|
+
);
|
|
365
|
+
const onSuccess = useCallback((result) => {
|
|
366
|
+
setState({ phase: "verified", result });
|
|
367
|
+
}, []);
|
|
368
|
+
const onExpired = useCallback((orderId) => {
|
|
369
|
+
setState({ phase: "expired", orderId });
|
|
370
|
+
}, []);
|
|
371
|
+
const reset = useCallback(() => setState({ phase: "idle" }), []);
|
|
372
|
+
return { state, createPayment, onSuccess, onExpired, reset };
|
|
373
|
+
}
|
|
374
|
+
export {
|
|
375
|
+
PaymentButton,
|
|
376
|
+
PaymentModal,
|
|
377
|
+
SeedhaPeProvider,
|
|
378
|
+
usePayment,
|
|
379
|
+
useSeedhaPe
|
|
380
|
+
};
|
|
381
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/PaymentButton.tsx","../src/PaymentModal.tsx","../src/usePayment.ts"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport { SeedhaPe } from '@seedhape/sdk';\n\ninterface SeedhaPeContextValue {\n client: SeedhaPe;\n}\n\nconst SeedhaPeContext = createContext<SeedhaPeContextValue | null>(null);\n\nexport function SeedhaPeProvider({\n apiKey,\n baseUrl,\n children,\n}: {\n apiKey: string;\n baseUrl?: string;\n children: React.ReactNode;\n}) {\n const client = useMemo(() => {\n const config: import('@seedhape/sdk').SeedhaPeConfig = { apiKey };\n if (baseUrl) config.baseUrl = baseUrl;\n return new SeedhaPe(config);\n }, [apiKey, baseUrl]);\n\n return (\n <SeedhaPeContext.Provider value={{ client }}>\n {children}\n </SeedhaPeContext.Provider>\n );\n}\n\nexport function useSeedhaPe(): SeedhaPe {\n const ctx = useContext(SeedhaPeContext);\n if (!ctx) throw new Error('useSeedhaPe must be used inside <SeedhaPeProvider>');\n return ctx.client;\n}\n","import React, { useState } from 'react';\nimport type { PaymentButtonProps } from './types.js';\nimport { PaymentModal } from './PaymentModal.js';\nimport { useSeedhaPe } from './provider.js';\n\nexport function PaymentButton({\n amount,\n description,\n customerEmail,\n customerPhone,\n expectedSenderName,\n metadata,\n onSuccess,\n onExpired,\n className = '',\n children = 'Pay Now',\n}: PaymentButtonProps) {\n const client = useSeedhaPe();\n const [orderId, setOrderId] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function handleClick() {\n setLoading(true);\n try {\n const opts: import('@seedhape/sdk').CreateOrderOptions = { amount };\n if (description) opts.description = description;\n if (customerEmail) opts.customerEmail = customerEmail;\n if (customerPhone) opts.customerPhone = customerPhone;\n if (expectedSenderName) opts.expectedSenderName = expectedSenderName;\n if (metadata) opts.metadata = metadata;\n const order = await client.createOrder(opts);\n setOrderId(order.id);\n } catch (err) {\n console.error('[SeedhaPe] Failed to create order:', err);\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <button\n onClick={handleClick}\n disabled={loading}\n className={className || 'sp-pay-btn'}\n style={\n !className\n ? {\n background: '#16a34a',\n color: 'white',\n border: 'none',\n padding: '12px 24px',\n borderRadius: '10px',\n fontWeight: 600,\n fontSize: '15px',\n cursor: loading ? 'not-allowed' : 'pointer',\n opacity: loading ? 0.7 : 1,\n }\n : undefined\n }\n >\n {loading ? 'Loading...' : children}\n </button>\n\n {orderId && (\n <PaymentModal\n orderId={orderId}\n open={true}\n onClose={() => setOrderId(null)}\n onSuccess={(result) => {\n setOrderId(null);\n onSuccess?.(result);\n }}\n onExpired={(id) => {\n setOrderId(null);\n onExpired?.(id);\n }}\n />\n )}\n </>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { PaymentModalProps } from './types.js';\n\n// API URL can be set via __SEEDHAPE_API_URL__ global, or defaults to production\ndeclare const __SEEDHAPE_API_URL__: string | undefined;\nconst API_URL: string =\n typeof __SEEDHAPE_API_URL__ !== 'undefined'\n ? __SEEDHAPE_API_URL__\n : 'https://api.seedhape.com';\n\ntype OrderData = {\n id: string;\n amount: number;\n description: string | null;\n status: string;\n upiUri: string;\n qrCode: string;\n expiresAt: string;\n expectedSenderName: string | null;\n};\n\nconst TERMINAL = ['VERIFIED', 'RESOLVED', 'EXPIRED', 'REJECTED'];\n\nconst baseStyles = {\n overlay: {\n position: 'fixed' as const, inset: 0,\n background: 'rgba(0,0,0,0.5)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n zIndex: 99999, fontFamily: 'system-ui, sans-serif',\n },\n card: {\n background: 'white', borderRadius: 16, padding: 28,\n width: 360, maxWidth: 'calc(100vw - 32px)', textAlign: 'center' as const,\n boxShadow: '0 25px 50px rgba(0,0,0,0.2)',\n },\n amountBox: {\n background: '#f0fdf4', borderRadius: 12, padding: '12px 16px',\n marginBottom: 20,\n },\n amountLabel: { fontSize: 12, color: '#15803d', marginBottom: 2 },\n amount: { fontSize: 28, fontWeight: 700, color: '#14532d', margin: 0 },\n input: {\n width: '100%', border: '1.5px solid #d1d5db', borderRadius: 10,\n padding: '10px 12px', fontSize: 14, boxSizing: 'border-box' as const,\n outline: 'none', marginBottom: 8,\n },\n inputError: { borderColor: '#f87171' },\n btnPrimary: {\n width: '100%', background: '#16a34a', color: 'white', border: 'none',\n borderRadius: 12, padding: '12px 0', fontSize: 15, fontWeight: 600,\n cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n },\n btnDisabled: { opacity: 0.5, cursor: 'not-allowed' as const },\n closeBtn: {\n marginTop: 14, background: 'none', border: 'none',\n color: '#9ca3af', fontSize: 13, cursor: 'pointer',\n },\n hint: { fontSize: 12, color: '#6b7280', lineHeight: 1.5, marginBottom: 12, textAlign: 'left' as const },\n errorText: { fontSize: 12, color: '#ef4444', marginBottom: 8, textAlign: 'left' as const },\n stepDots: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 14 },\n dot: (active: boolean) => ({\n width: 24, height: 6, borderRadius: 3,\n background: active ? '#16a34a' : '#e5e7eb',\n }),\n};\n\nexport function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps) {\n const [order, setOrder] = useState<OrderData | null>(null);\n const [nameInput, setNameInput] = useState('');\n const [nameError, setNameError] = useState<string | null>(null);\n const [savingName, setSavingName] = useState(false);\n const [nameConfirmed, setNameConfirmed] = useState(false);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!open || !orderId) return;\n setOrder(null);\n setNameInput('');\n setNameError(null);\n setNameConfirmed(false);\n fetchOrder();\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [open, orderId]);\n\n async function fetchOrder() {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n // Skip name gate if the merchant already supplied it at order creation time\n if (data.expectedSenderName) {\n setNameInput(data.expectedSenderName);\n setNameConfirmed(true);\n }\n if (!TERMINAL.includes(data.status)) startPolling();\n }\n\n function startPolling() {\n pollRef.current = setInterval(async () => {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n if (TERMINAL.includes(data.status)) {\n if (pollRef.current) clearInterval(pollRef.current);\n handleTerminal(data);\n }\n }, 3000);\n }\n\n function handleTerminal(data: OrderData) {\n if (data.status === 'VERIFIED' || data.status === 'RESOLVED') {\n onSuccess?.({ orderId: data.id, status: data.status as 'VERIFIED', amount: data.amount });\n } else if (data.status === 'EXPIRED') {\n onExpired?.(data.id);\n }\n }\n\n async function confirmName() {\n const name = nameInput.trim();\n if (name.length < 2) { setNameError('Enter at least 2 characters.'); return; }\n setSavingName(true);\n setNameError(null);\n try {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ expectedSenderName: name }),\n });\n if (!res.ok) throw new Error('Failed');\n setNameConfirmed(true);\n } catch {\n setNameError('Could not save name. Please try again.');\n } finally {\n setSavingName(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div style={baseStyles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>\n <div style={baseStyles.card}>\n {!order ? (\n <p style={{ color: '#9ca3af' }}>Loading…</p>\n ) : (order.status === 'VERIFIED' || order.status === 'RESOLVED') ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>✅</div>\n <p style={{ fontWeight: 700, fontSize: 18, color: '#16a34a', margin: '0 0 4px' }}>Payment Verified!</p>\n <p style={{ fontSize: 26, fontWeight: 700, color: '#111', margin: 0 }}>\n ₹{(order.amount / 100).toFixed(2)}\n </p>\n </>\n ) : order.status === 'EXPIRED' ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>⏰</div>\n <p style={{ fontWeight: 600, fontSize: 18, color: '#dc2626' }}>Link Expired</p>\n </>\n ) : !nameConfirmed ? (\n /* ── Step 1: Name gate ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n <p style={{ fontWeight: 700, fontSize: 15, textAlign: 'left', marginBottom: 6 }}>Enter your name</p>\n <p style={baseStyles.hint}>\n Enter your name exactly as shown in your UPI app. This is used to instantly match your payment.\n </p>\n <input\n style={{ ...baseStyles.input, ...(nameError ? baseStyles.inputError : {}) }}\n value={nameInput}\n onChange={(e) => { setNameInput(e.target.value); setNameError(null); }}\n onKeyDown={(e) => e.key === 'Enter' && confirmName()}\n placeholder=\"e.g. Rahul Sharma\"\n autoFocus\n />\n {nameError && <p style={baseStyles.errorText}>{nameError}</p>}\n <button\n style={{ ...baseStyles.btnPrimary, ...(savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {}) }}\n onClick={confirmName}\n disabled={savingName || nameInput.trim().length < 2}\n >\n {savingName ? 'Saving…' : 'Continue →'}\n </button>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(true)} />\n <div style={baseStyles.dot(false)} />\n </div>\n </>\n ) : (\n /* ── Step 2: QR + Pay ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n {order.description && (\n <p style={{ fontSize: 14, color: '#4b5563', marginBottom: 12 }}>{order.description}</p>\n )}\n {order.qrCode && (\n <img src={order.qrCode} width={200} height={200} style={{ borderRadius: 8, marginBottom: 14 }} alt=\"UPI QR\" />\n )}\n <a\n href={order.upiUri}\n style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n background: '#16a34a', color: 'white',\n padding: '12px 0', borderRadius: 12, textDecoration: 'none',\n fontWeight: 600, fontSize: 15, marginBottom: 10,\n }}\n >\n Open UPI App\n </a>\n <p style={{ fontSize: 12, color: '#9ca3af', marginBottom: 2 }}>⏳ Waiting for payment…</p>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(false)} />\n <div style={baseStyles.dot(true)} />\n </div>\n </>\n )}\n\n <button style={baseStyles.closeBtn} onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport type { OrderData, PaymentResult } from '@seedhape/sdk';\n\nimport { useSeedhaPe } from './provider.js';\n\ntype PaymentState =\n | { phase: 'idle' }\n | { phase: 'creating' }\n | { phase: 'pending'; order: OrderData }\n | { phase: 'verified'; result: PaymentResult }\n | { phase: 'expired'; orderId: string }\n | { phase: 'error'; error: string };\n\nexport function usePayment() {\n const client = useSeedhaPe();\n const [state, setState] = useState<PaymentState>({ phase: 'idle' });\n\n const createPayment = useCallback(\n async (options: {\n amount: number;\n description?: string;\n customerEmail?: string;\n customerPhone?: string;\n metadata?: Record<string, unknown>;\n }) => {\n setState({ phase: 'creating' });\n try {\n const order = await client.createOrder(options);\n setState({ phase: 'pending', order });\n return order;\n } catch (err) {\n setState({ phase: 'error', error: String(err) });\n throw err;\n }\n },\n [client],\n );\n\n const onSuccess = useCallback((result: PaymentResult) => {\n setState({ phase: 'verified', result });\n }, []);\n\n const onExpired = useCallback((orderId: string) => {\n setState({ phase: 'expired', orderId });\n }, []);\n\n const reset = useCallback(() => setState({ phase: 'idle' }), []);\n\n return { state, createPayment, onSuccess, onExpired, reset };\n}\n"],"mappings":"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","names":["useState","jsx","Fragment","jsx","jsxs","useState","useState","useState"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seedhape/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SeedhaPe React components — PaymentButton, PaymentModal, usePayment hook",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"require": "./dist/index.cjs"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"module": "./dist/index.mjs",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@seedhape/sdk": "0.1.0",
|
|
20
|
+
"@seedhape/shared": "0.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/react": "^19.0.7",
|
|
24
|
+
"tsup": "^8.3.5",
|
|
25
|
+
"typescript": "^5.7.2",
|
|
26
|
+
"@seedhape/typescript-config": "0.0.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"dev": "tsup --watch",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"clean": "rm -rf dist"
|
|
36
|
+
}
|
|
37
|
+
}
|