@nozle-js/react 0.8.0 → 0.9.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 +308 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -27
- package/dist/index.d.ts +97 -27
- package/dist/index.js +309 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,21 +31,29 @@ var BillingContext = React.createContext(null);
|
|
|
31
31
|
function BillingProvider({
|
|
32
32
|
publishableKey,
|
|
33
33
|
createCheckout,
|
|
34
|
+
verifyCheckout,
|
|
35
|
+
getCheckoutStatus,
|
|
34
36
|
baseUrl = "https://api.nozle.app/engine",
|
|
35
37
|
children
|
|
36
38
|
}) {
|
|
37
39
|
if (!publishableKey.startsWith("pk_")) {
|
|
38
|
-
throw new Error(
|
|
40
|
+
throw new Error(
|
|
41
|
+
"BillingProvider publishableKey must be a publishable key (pk_)"
|
|
42
|
+
);
|
|
39
43
|
}
|
|
40
44
|
const client = React.useMemo(
|
|
41
45
|
() => createClient(publishableKey, baseUrl),
|
|
42
46
|
[publishableKey, baseUrl]
|
|
43
47
|
);
|
|
44
48
|
const contextValue = React.useMemo(
|
|
45
|
-
() => ({ client, createCheckout }),
|
|
46
|
-
[client, createCheckout]
|
|
49
|
+
() => ({ client, createCheckout, verifyCheckout, getCheckoutStatus }),
|
|
50
|
+
[client, createCheckout, verifyCheckout, getCheckoutStatus]
|
|
51
|
+
);
|
|
52
|
+
return React__default.default.createElement(
|
|
53
|
+
BillingContext.Provider,
|
|
54
|
+
{ value: contextValue },
|
|
55
|
+
children
|
|
47
56
|
);
|
|
48
|
-
return React__default.default.createElement(BillingContext.Provider, { value: contextValue }, children);
|
|
49
57
|
}
|
|
50
58
|
function useOptionalBillingContext() {
|
|
51
59
|
return React.useContext(BillingContext);
|
|
@@ -116,7 +124,11 @@ function useCheckout() {
|
|
|
116
124
|
navigateToCheckout(result.url);
|
|
117
125
|
return null;
|
|
118
126
|
}
|
|
119
|
-
if ("type" in result &&
|
|
127
|
+
if ("type" in result && result.type === "hosted") {
|
|
128
|
+
navigateToCheckout(result.payment_url);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
if ("type" in result && ["completed", "scheduled", "razorpay", "processing"].includes(result.type)) {
|
|
120
132
|
return null;
|
|
121
133
|
}
|
|
122
134
|
throw new Error("Checkout response did not include a supported result type");
|
|
@@ -132,20 +144,151 @@ function useCheckout() {
|
|
|
132
144
|
);
|
|
133
145
|
return { fetchClientSecret, checkout, isLoading, error };
|
|
134
146
|
}
|
|
147
|
+
|
|
148
|
+
// src/components/billing/razorpay-checkout.ts
|
|
149
|
+
var loadingScript;
|
|
135
150
|
function loadRazorpayScript() {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
151
|
+
if (typeof window === "undefined")
|
|
152
|
+
return Promise.reject(new Error("Razorpay checkout requires a browser"));
|
|
153
|
+
if (window.Razorpay) return Promise.resolve();
|
|
154
|
+
if (loadingScript) return loadingScript;
|
|
155
|
+
loadingScript = new Promise((resolve, reject) => {
|
|
156
|
+
const existing = document.querySelector(
|
|
157
|
+
'script[src="https://checkout.razorpay.com/v1/checkout.js"]'
|
|
158
|
+
);
|
|
159
|
+
const script = existing || document.createElement("script");
|
|
160
|
+
const finish = (error) => {
|
|
161
|
+
clearTimeout(timer);
|
|
162
|
+
script.removeEventListener("load", onLoad);
|
|
163
|
+
script.removeEventListener("error", onError);
|
|
164
|
+
if (error) {
|
|
165
|
+
script.remove();
|
|
166
|
+
reject(error);
|
|
167
|
+
} else {
|
|
168
|
+
resolve();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const onLoad = () => finish(
|
|
172
|
+
window.Razorpay ? void 0 : new Error("Razorpay checkout did not initialize")
|
|
173
|
+
);
|
|
174
|
+
const onError = () => finish(new Error("Failed to load Razorpay checkout"));
|
|
175
|
+
const timer = setTimeout(
|
|
176
|
+
() => finish(new Error("Razorpay checkout timed out while loading")),
|
|
177
|
+
15e3
|
|
178
|
+
);
|
|
179
|
+
script.addEventListener("load", onLoad);
|
|
180
|
+
script.addEventListener("error", onError);
|
|
181
|
+
if (!existing) {
|
|
182
|
+
script.id = "razorpay-js";
|
|
183
|
+
script.src = "https://checkout.razorpay.com/v1/checkout.js";
|
|
184
|
+
document.body.appendChild(script);
|
|
140
185
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
186
|
+
}).catch((error) => {
|
|
187
|
+
loadingScript = void 0;
|
|
188
|
+
throw error;
|
|
189
|
+
});
|
|
190
|
+
return loadingScript;
|
|
191
|
+
}
|
|
192
|
+
function checkStatus(status, id) {
|
|
193
|
+
if (status.checkout_id !== id || status.provider !== "razorpay")
|
|
194
|
+
throw new Error("Checkout status did not match this checkout");
|
|
195
|
+
if (["failed", "expired", "needs_review"].includes(status.status))
|
|
196
|
+
throw new Error(`Checkout ${status.status.replaceAll("_", " ")}`);
|
|
197
|
+
}
|
|
198
|
+
async function waitForCheckout(id, actions, initial, phase = "confirm") {
|
|
199
|
+
let status = initial;
|
|
200
|
+
if (!status && !actions.getCheckoutStatus)
|
|
201
|
+
throw new Error("BillingProvider getCheckoutStatus callback is required");
|
|
202
|
+
for (let attempt = 0; attempt < 30; attempt++) {
|
|
203
|
+
status = status || await actions.getCheckoutStatus(id);
|
|
204
|
+
checkStatus(status, id);
|
|
205
|
+
if (status.status === "succeeded" && status.fulfillment_status === "succeeded" || phase === "prepare" && status.status === "awaiting_payment")
|
|
206
|
+
return status;
|
|
207
|
+
actions.onProcessing?.(status);
|
|
208
|
+
if (!actions.getCheckoutStatus) return status;
|
|
209
|
+
if (attempt < 29) {
|
|
210
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
211
|
+
status = void 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return status;
|
|
215
|
+
}
|
|
216
|
+
async function openRazorpayCheckout(result, actions) {
|
|
217
|
+
if (!result.checkout_id || !result.key_id || !result.order_id)
|
|
218
|
+
throw new Error(
|
|
219
|
+
"Razorpay checkout requires server-issued checkout_id, key_id and order_id"
|
|
220
|
+
);
|
|
221
|
+
if (!actions.verifyCheckout)
|
|
222
|
+
throw new Error(
|
|
223
|
+
"BillingProvider verifyCheckout callback is required for Razorpay checkout"
|
|
224
|
+
);
|
|
225
|
+
await loadRazorpayScript();
|
|
226
|
+
await new Promise((resolve, reject) => {
|
|
227
|
+
let finishing = false;
|
|
228
|
+
const checkout = new window.Razorpay({
|
|
229
|
+
key: result.key_id,
|
|
230
|
+
order_id: result.order_id,
|
|
231
|
+
amount: result.amount_cents,
|
|
232
|
+
currency: result.currency,
|
|
233
|
+
...result.recurring && {
|
|
234
|
+
customer_id: result.customer_id,
|
|
235
|
+
recurring: "1"
|
|
236
|
+
},
|
|
237
|
+
handler: (response) => {
|
|
238
|
+
if (finishing) return;
|
|
239
|
+
finishing = true;
|
|
240
|
+
void (async () => {
|
|
241
|
+
const verified = await actions.verifyCheckout(
|
|
242
|
+
result.checkout_id,
|
|
243
|
+
response
|
|
244
|
+
);
|
|
245
|
+
const status = await waitForCheckout(
|
|
246
|
+
result.checkout_id,
|
|
247
|
+
actions,
|
|
248
|
+
verified
|
|
249
|
+
);
|
|
250
|
+
if (status.status === "succeeded" && status.fulfillment_status === "succeeded")
|
|
251
|
+
actions.onSuccess?.(response.razorpay_payment_id);
|
|
252
|
+
else actions.onProcessing?.(status);
|
|
253
|
+
resolve();
|
|
254
|
+
})().catch(reject);
|
|
255
|
+
},
|
|
256
|
+
modal: {
|
|
257
|
+
ondismiss: () => {
|
|
258
|
+
if (!finishing) {
|
|
259
|
+
finishing = true;
|
|
260
|
+
actions.onDismiss?.();
|
|
261
|
+
resolve();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
checkout.on("payment.failed", () => {
|
|
267
|
+
if (finishing) return;
|
|
268
|
+
finishing = true;
|
|
269
|
+
checkout.close();
|
|
270
|
+
reject(new Error("Payment failed. You can retry checkout."));
|
|
271
|
+
});
|
|
272
|
+
checkout.open();
|
|
147
273
|
});
|
|
148
274
|
}
|
|
275
|
+
async function resumeCheckout(result, actions) {
|
|
276
|
+
const status = await waitForCheckout(
|
|
277
|
+
result.checkout_id,
|
|
278
|
+
actions,
|
|
279
|
+
void 0,
|
|
280
|
+
"prepare"
|
|
281
|
+
);
|
|
282
|
+
if (status.status === "awaiting_payment") return status.checkout;
|
|
283
|
+
if (status.status === "succeeded" && status.fulfillment_status === "succeeded")
|
|
284
|
+
return {
|
|
285
|
+
type: "completed",
|
|
286
|
+
status: "succeeded",
|
|
287
|
+
invoice_id: status.invoice_id || void 0
|
|
288
|
+
};
|
|
289
|
+
actions.onProcessing?.(status);
|
|
290
|
+
return void 0;
|
|
291
|
+
}
|
|
149
292
|
async function handleCheckoutResult(result, options) {
|
|
150
293
|
if ("type" in result && result.type === "scheduled") {
|
|
151
294
|
options.onScheduled?.(result);
|
|
@@ -156,14 +299,16 @@ async function handleCheckoutResult(result, options) {
|
|
|
156
299
|
return;
|
|
157
300
|
}
|
|
158
301
|
if ("type" in result && result.type === "razorpay") {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
302
|
+
await openRazorpayCheckout(result, options);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if ("type" in result && result.type === "processing") {
|
|
306
|
+
const next = await resumeCheckout(result, options);
|
|
307
|
+
if (next) await handleCheckoutResult(next, options);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if ("type" in result && result.type === "hosted") {
|
|
311
|
+
window.location.assign(result.payment_url);
|
|
167
312
|
return;
|
|
168
313
|
}
|
|
169
314
|
if ("url" in result && result.url) {
|
|
@@ -176,7 +321,10 @@ async function handleCheckoutResult(result, options) {
|
|
|
176
321
|
options.onStripeClientSecret(clientSecret);
|
|
177
322
|
return;
|
|
178
323
|
}
|
|
179
|
-
if (clientSecret)
|
|
324
|
+
if (clientSecret)
|
|
325
|
+
throw new Error(
|
|
326
|
+
"onStripeClientSecret is required for embedded Stripe checkout"
|
|
327
|
+
);
|
|
180
328
|
throw new Error("Stripe checkout did not include a URL or client secret");
|
|
181
329
|
}
|
|
182
330
|
throw new Error("Unknown checkout response format");
|
|
@@ -189,30 +337,58 @@ function CheckoutButton({
|
|
|
189
337
|
style,
|
|
190
338
|
onError,
|
|
191
339
|
razorpayKeyId,
|
|
340
|
+
registerMandate,
|
|
341
|
+
onProcessing,
|
|
342
|
+
onDismiss,
|
|
192
343
|
onStripeClientSecret,
|
|
193
344
|
onSuccess,
|
|
194
345
|
onComplete,
|
|
195
346
|
onScheduled
|
|
196
347
|
}) {
|
|
197
|
-
const { createCheckout } = useBillingContext();
|
|
348
|
+
const { createCheckout, verifyCheckout, getCheckoutStatus } = useBillingContext();
|
|
349
|
+
const attempt = React.useRef(void 0);
|
|
350
|
+
const inFlight = React.useRef(false);
|
|
351
|
+
const [processing, setProcessing] = React.useState(false);
|
|
198
352
|
const [loading, setLoading] = React.useState(false);
|
|
199
353
|
const [error, setError] = React.useState(null);
|
|
200
354
|
async function handleClick() {
|
|
355
|
+
if (inFlight.current) return;
|
|
356
|
+
inFlight.current = true;
|
|
201
357
|
setLoading(true);
|
|
358
|
+
setProcessing(false);
|
|
202
359
|
setError(null);
|
|
203
360
|
try {
|
|
204
361
|
if (!createCheckout) {
|
|
205
|
-
throw new Error(
|
|
362
|
+
throw new Error(
|
|
363
|
+
"BillingProvider createCheckout callback is required for checkout"
|
|
364
|
+
);
|
|
206
365
|
}
|
|
366
|
+
if (attempt.current?.plan !== planCode)
|
|
367
|
+
attempt.current = { plan: planCode, key: crypto.randomUUID() };
|
|
207
368
|
const result = await createCheckout({
|
|
369
|
+
idempotencyKey: attempt.current.key,
|
|
370
|
+
...registerMandate !== void 0 && { registerMandate },
|
|
208
371
|
planCode,
|
|
209
372
|
returnUrl: returnUrl ?? window.location.href
|
|
210
373
|
});
|
|
211
374
|
await handleCheckoutResult(result, {
|
|
212
375
|
razorpayKeyId,
|
|
376
|
+
verifyCheckout,
|
|
377
|
+
getCheckoutStatus,
|
|
378
|
+
onProcessing: (status) => {
|
|
379
|
+
setProcessing(true);
|
|
380
|
+
onProcessing?.(status);
|
|
381
|
+
},
|
|
382
|
+
onDismiss,
|
|
213
383
|
onStripeClientSecret,
|
|
214
|
-
onSuccess
|
|
215
|
-
|
|
384
|
+
onSuccess: (id) => {
|
|
385
|
+
setProcessing(false);
|
|
386
|
+
onSuccess?.(id);
|
|
387
|
+
},
|
|
388
|
+
onComplete: (completed) => {
|
|
389
|
+
setProcessing(false);
|
|
390
|
+
onComplete?.(completed);
|
|
391
|
+
},
|
|
216
392
|
onScheduled
|
|
217
393
|
});
|
|
218
394
|
} catch (cause) {
|
|
@@ -220,6 +396,7 @@ function CheckoutButton({
|
|
|
220
396
|
setError(checkoutError);
|
|
221
397
|
onError?.(checkoutError);
|
|
222
398
|
} finally {
|
|
399
|
+
inFlight.current = false;
|
|
223
400
|
setLoading(false);
|
|
224
401
|
}
|
|
225
402
|
}
|
|
@@ -246,6 +423,7 @@ function CheckoutButton({
|
|
|
246
423
|
children: loading ? "Loading..." : label
|
|
247
424
|
}
|
|
248
425
|
),
|
|
426
|
+
processing && /* @__PURE__ */ jsxRuntime.jsx("span", { role: "status", children: "Payment is processing. Confirmation may take a little while." }),
|
|
249
427
|
error && /* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", children: error.message })
|
|
250
428
|
] });
|
|
251
429
|
}
|
|
@@ -518,6 +696,7 @@ function PricingTable({
|
|
|
518
696
|
const [currentPlan, setCurrentPlan] = React.useState(currentPlanCode ?? null);
|
|
519
697
|
const [isAnnual, setIsAnnual] = React.useState(false);
|
|
520
698
|
const [loading, setLoading] = React.useState(!propPlans);
|
|
699
|
+
const [processing, setProcessing] = React.useState(false);
|
|
521
700
|
const [checkoutError, setCheckoutError] = React.useState(null);
|
|
522
701
|
React.useEffect(() => {
|
|
523
702
|
if (propPlans) {
|
|
@@ -560,7 +739,14 @@ function PricingTable({
|
|
|
560
739
|
returnUrl: returnUrl ?? window.location.href
|
|
561
740
|
});
|
|
562
741
|
onCheckoutResult?.(result);
|
|
563
|
-
await handleCheckoutResult(result, {
|
|
742
|
+
await handleCheckoutResult(result, {
|
|
743
|
+
onStripeClientSecret,
|
|
744
|
+
verifyCheckout: billing?.verifyCheckout,
|
|
745
|
+
getCheckoutStatus: billing?.getCheckoutStatus,
|
|
746
|
+
onProcessing: () => setProcessing(true),
|
|
747
|
+
onSuccess: () => setProcessing(false),
|
|
748
|
+
onComplete: () => setProcessing(false)
|
|
749
|
+
});
|
|
564
750
|
} catch (cause) {
|
|
565
751
|
const error = cause instanceof Error ? cause : new Error("Checkout failed");
|
|
566
752
|
setCheckoutError(error.message);
|
|
@@ -576,6 +762,7 @@ function PricingTable({
|
|
|
576
762
|
background: C.bg
|
|
577
763
|
}, children: [
|
|
578
764
|
showToggle && hasAnnual && /* @__PURE__ */ jsxRuntime.jsx(Toggle, { isAnnual, onChange: setIsAnnual }),
|
|
765
|
+
processing && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Payment is processing. Confirmation may take a little while." }),
|
|
579
766
|
checkoutError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", children: checkoutError }),
|
|
580
767
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
581
768
|
display: "grid",
|
|
@@ -929,7 +1116,16 @@ function CheckoutInner({
|
|
|
929
1116
|
}
|
|
930
1117
|
}
|
|
931
1118
|
),
|
|
932
|
-
error !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1119
|
+
error !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1120
|
+
"p",
|
|
1121
|
+
{
|
|
1122
|
+
style: {
|
|
1123
|
+
color: "var(--nozle-destructive, #dc2626)",
|
|
1124
|
+
margin: "0.5rem 0 0"
|
|
1125
|
+
},
|
|
1126
|
+
children: error.message
|
|
1127
|
+
}
|
|
1128
|
+
),
|
|
933
1129
|
children ?? /* @__PURE__ */ jsxRuntime.jsx(
|
|
934
1130
|
"button",
|
|
935
1131
|
{
|
|
@@ -954,7 +1150,7 @@ function CheckoutInner({
|
|
|
954
1150
|
)
|
|
955
1151
|
] }) });
|
|
956
1152
|
}
|
|
957
|
-
function
|
|
1153
|
+
function StripeCheckout({
|
|
958
1154
|
clientSecret,
|
|
959
1155
|
publishableKey,
|
|
960
1156
|
stripeAccount,
|
|
@@ -978,7 +1174,14 @@ function Checkout({
|
|
|
978
1174
|
[clientSecret, onComplete]
|
|
979
1175
|
);
|
|
980
1176
|
if (clientSecret.startsWith("cs_")) {
|
|
981
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1177
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1178
|
+
reactStripeJs.EmbeddedCheckoutProvider,
|
|
1179
|
+
{
|
|
1180
|
+
stripe: stripePromise,
|
|
1181
|
+
options: embeddedOptions,
|
|
1182
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.EmbeddedCheckout, {})
|
|
1183
|
+
}
|
|
1184
|
+
) });
|
|
982
1185
|
}
|
|
983
1186
|
const options = { clientSecret, appearance };
|
|
984
1187
|
return /* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.Elements, { stripe: stripePromise, options, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -995,6 +1198,65 @@ function Checkout({
|
|
|
995
1198
|
}
|
|
996
1199
|
) }, clientSecret);
|
|
997
1200
|
}
|
|
1201
|
+
function ProviderCheckout(props) {
|
|
1202
|
+
const billing = useOptionalBillingContext();
|
|
1203
|
+
const [busy, setBusy] = React.useState(false);
|
|
1204
|
+
const [error, setError] = React.useState(null);
|
|
1205
|
+
const [processing, setProcessing] = React.useState(false);
|
|
1206
|
+
const pay = async () => {
|
|
1207
|
+
if (busy) return;
|
|
1208
|
+
setBusy(true);
|
|
1209
|
+
setError(null);
|
|
1210
|
+
try {
|
|
1211
|
+
await handleCheckoutResult(props.checkout, {
|
|
1212
|
+
verifyCheckout: billing?.verifyCheckout,
|
|
1213
|
+
getCheckoutStatus: billing?.getCheckoutStatus,
|
|
1214
|
+
onSuccess: (id) => {
|
|
1215
|
+
setProcessing(false);
|
|
1216
|
+
props.onSuccess?.(id);
|
|
1217
|
+
props.onComplete?.();
|
|
1218
|
+
},
|
|
1219
|
+
onComplete: () => {
|
|
1220
|
+
setProcessing(false);
|
|
1221
|
+
props.onComplete?.();
|
|
1222
|
+
},
|
|
1223
|
+
onProcessing: (status) => {
|
|
1224
|
+
setProcessing(true);
|
|
1225
|
+
props.onProcessing?.(status);
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
} catch (cause) {
|
|
1229
|
+
const failure = cause instanceof Error ? cause : new Error("Checkout failed");
|
|
1230
|
+
setError(failure);
|
|
1231
|
+
props.onError?.(failure);
|
|
1232
|
+
} finally {
|
|
1233
|
+
setBusy(false);
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1237
|
+
CheckoutContext.Provider,
|
|
1238
|
+
{
|
|
1239
|
+
value: { confirmPayment: pay, isProcessing: busy, error },
|
|
1240
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: props.className, children: [
|
|
1241
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1242
|
+
"button",
|
|
1243
|
+
{
|
|
1244
|
+
type: "button",
|
|
1245
|
+
disabled: busy,
|
|
1246
|
+
"aria-busy": busy,
|
|
1247
|
+
onClick: () => void pay(),
|
|
1248
|
+
children: busy ? "Processing\u2026" : props.submitLabel || "Pay now"
|
|
1249
|
+
}
|
|
1250
|
+
),
|
|
1251
|
+
processing && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Payment is processing. Confirmation may take a little while." }),
|
|
1252
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", children: error.message })
|
|
1253
|
+
] })
|
|
1254
|
+
}
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
function Checkout(props) {
|
|
1258
|
+
return "checkout" in props ? /* @__PURE__ */ jsxRuntime.jsx(ProviderCheckout, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(StripeCheckout, { ...props });
|
|
1259
|
+
}
|
|
998
1260
|
function UpgradeModal({
|
|
999
1261
|
isOpen,
|
|
1000
1262
|
planCode,
|
|
@@ -1008,7 +1270,8 @@ function UpgradeModal({
|
|
|
1008
1270
|
onCancel,
|
|
1009
1271
|
onError
|
|
1010
1272
|
}) {
|
|
1011
|
-
const { createCheckout } = useBillingContext();
|
|
1273
|
+
const { createCheckout, verifyCheckout, getCheckoutStatus } = useBillingContext();
|
|
1274
|
+
const [processing, setProcessing] = React.useState(false);
|
|
1012
1275
|
const [error, setError] = React.useState(null);
|
|
1013
1276
|
const [confirming, setConfirming] = React.useState(false);
|
|
1014
1277
|
async function handleConfirm() {
|
|
@@ -1023,11 +1286,21 @@ function UpgradeModal({
|
|
|
1023
1286
|
returnUrl: returnUrl ?? window.location.href
|
|
1024
1287
|
});
|
|
1025
1288
|
await handleCheckoutResult(result, {
|
|
1289
|
+
verifyCheckout,
|
|
1290
|
+
getCheckoutStatus,
|
|
1291
|
+
onSuccess: () => {
|
|
1292
|
+
setProcessing(false);
|
|
1293
|
+
onCompleted?.();
|
|
1294
|
+
},
|
|
1295
|
+
onProcessing: () => setProcessing(true),
|
|
1026
1296
|
onStripeClientSecret: (clientSecret) => {
|
|
1027
1297
|
onStripeClientSecret?.(clientSecret);
|
|
1028
1298
|
onCheckoutStarted?.();
|
|
1029
1299
|
},
|
|
1030
|
-
onComplete: () =>
|
|
1300
|
+
onComplete: () => {
|
|
1301
|
+
setProcessing(false);
|
|
1302
|
+
onCompleted?.();
|
|
1303
|
+
},
|
|
1031
1304
|
onScheduled: () => onScheduled?.()
|
|
1032
1305
|
});
|
|
1033
1306
|
onConfirm?.();
|
|
@@ -1070,6 +1343,7 @@ function UpgradeModal({
|
|
|
1070
1343
|
},
|
|
1071
1344
|
children: [
|
|
1072
1345
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1.25rem", fontWeight: 600, margin: "0 0 1rem" }, children: "Confirm plan change" }),
|
|
1346
|
+
processing && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Payment is processing. Confirmation may take a little while." }),
|
|
1073
1347
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", style: { color: "oklch(0.6 0.2 25)" }, children: error }),
|
|
1074
1348
|
preview && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "1.5rem" }, children: [
|
|
1075
1349
|
/* @__PURE__ */ jsxRuntime.jsxs(
|