@blocklet/payment-react 1.21.16 → 1.21.17

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.
Files changed (37) hide show
  1. package/.aigne/doc-smith/translation-cache.yaml +11 -0
  2. package/es/components/over-due-invoice-payment.js +86 -21
  3. package/es/components/payment-beneficiaries.js +3 -3
  4. package/es/components/stripe-payment-action.d.ts +16 -0
  5. package/es/components/stripe-payment-action.js +164 -0
  6. package/es/history/invoice/list.js +58 -2
  7. package/es/index.d.ts +3 -1
  8. package/es/index.js +2 -0
  9. package/es/libs/util.d.ts +1 -0
  10. package/es/libs/util.js +16 -0
  11. package/es/locales/en.js +18 -3
  12. package/es/locales/zh.js +12 -3
  13. package/es/payment/form/stripe/form.d.ts +4 -1
  14. package/es/payment/form/stripe/form.js +9 -5
  15. package/lib/components/over-due-invoice-payment.js +99 -31
  16. package/lib/components/payment-beneficiaries.js +3 -2
  17. package/lib/components/stripe-payment-action.d.ts +16 -0
  18. package/lib/components/stripe-payment-action.js +191 -0
  19. package/lib/history/invoice/list.js +58 -10
  20. package/lib/index.d.ts +3 -1
  21. package/lib/index.js +8 -0
  22. package/lib/libs/util.d.ts +1 -0
  23. package/lib/libs/util.js +17 -0
  24. package/lib/locales/en.js +18 -3
  25. package/lib/locales/zh.js +12 -3
  26. package/lib/payment/form/stripe/form.d.ts +4 -1
  27. package/lib/payment/form/stripe/form.js +9 -5
  28. package/package.json +3 -3
  29. package/src/components/over-due-invoice-payment.tsx +101 -29
  30. package/src/components/payment-beneficiaries.tsx +3 -3
  31. package/src/components/stripe-payment-action.tsx +220 -0
  32. package/src/history/invoice/list.tsx +67 -13
  33. package/src/index.ts +3 -0
  34. package/src/libs/util.ts +17 -0
  35. package/src/locales/en.tsx +16 -0
  36. package/src/locales/zh.tsx +10 -0
  37. package/src/payment/form/stripe/form.tsx +9 -2
@@ -23,7 +23,8 @@ function StripeCheckoutForm({
23
23
  customer,
24
24
  mode,
25
25
  onConfirm,
26
- returnUrl = ""
26
+ returnUrl = "",
27
+ submitButtonText = ""
27
28
  }) {
28
29
  const stripe = useStripe();
29
30
  const elements = useElements();
@@ -201,7 +202,7 @@ function StripeCheckoutForm({
201
202
  variant: "contained",
202
203
  color: "primary",
203
204
  size: "large",
204
- children: t("payment.checkout.continue", { action: t(`payment.checkout.${mode}`) })
205
+ children: submitButtonText || t("payment.checkout.continue", { action: t(`payment.checkout.${mode}`) })
205
206
  }
206
207
  ),
207
208
  state.message && /* @__PURE__ */ jsx(Typography, { sx: { mt: 1, color: "error.main" }, children: state.message })
@@ -224,7 +225,9 @@ export default function StripeCheckout({
224
225
  customer,
225
226
  onConfirm,
226
227
  onCancel,
227
- returnUrl = ""
228
+ returnUrl = "",
229
+ title = "",
230
+ submitButtonText = ""
228
231
  }) {
229
232
  const stripePromise = loadStripe(publicKey);
230
233
  const { isMobile } = useMobile();
@@ -244,7 +247,7 @@ export default function StripeCheckout({
244
247
  return /* @__PURE__ */ jsx(
245
248
  Dialog,
246
249
  {
247
- title: t("payment.checkout.cardPay", { action: t(`payment.checkout.${mode}`) }),
250
+ title: title || t("payment.checkout.cardPay", { action: t(`payment.checkout.${mode}`) }),
248
251
  showCloseButton: state.closable,
249
252
  open: state.open,
250
253
  onClose: handleClose,
@@ -297,7 +300,8 @@ export default function StripeCheckout({
297
300
  mode,
298
301
  customer,
299
302
  onConfirm,
300
- returnUrl
303
+ returnUrl,
304
+ submitButtonText
301
305
  }
302
306
  )
303
307
  }
@@ -20,6 +20,7 @@ var _util = require("../libs/util");
20
20
  var _subscription = require("../hooks/subscription");
21
21
  var _api = _interopRequireDefault(require("../libs/api"));
22
22
  var _loadingButton = _interopRequireDefault(require("./loading-button"));
23
+ var _stripePaymentAction = _interopRequireDefault(require("./stripe-payment-action"));
23
24
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
24
25
  const fetchOverdueInvoices = async params => {
25
26
  if (!params.subscriptionId && !params.customerId) {
@@ -64,10 +65,15 @@ function OverdueInvoicePayment({
64
65
  const [dialogOpen, setDialogOpen] = (0, _react.useState)(dialogProps.open || false);
65
66
  const [processedCurrencies, setProcessedCurrencies] = (0, _react.useState)({});
66
67
  const [paymentStatus, setPaymentStatus] = (0, _react.useState)({});
68
+ const [stripePaymentInProgress, setStripePaymentInProgress] = (0, _react.useState)({});
69
+ const stripePaymentInProgressRef = (0, _react.useRef)(stripePaymentInProgress);
67
70
  const sourceType = subscriptionId ? "subscription" : "customer";
68
71
  const effectiveCustomerId = customerId || session?.user?.did;
69
72
  const sourceId = subscriptionId || effectiveCustomerId;
70
73
  const customerIdRef = (0, _react.useRef)(effectiveCustomerId);
74
+ (0, _react.useEffect)(() => {
75
+ stripePaymentInProgressRef.current = stripePaymentInProgress;
76
+ }, [stripePaymentInProgress]);
71
77
  const {
72
78
  data = {
73
79
  summary: {},
@@ -104,6 +110,33 @@ function OverdueInvoicePayment({
104
110
  return Object.values(data.summary);
105
111
  }, [data?.summary]);
106
112
  const debouncedHandleInvoicePaid = (0, _debounce.default)(async currencyId => {
113
+ if (stripePaymentInProgressRef.current[currencyId]) {
114
+ try {
115
+ const checkData = await fetchOverdueInvoices({
116
+ subscriptionId,
117
+ customerId: effectiveCustomerId,
118
+ authToken
119
+ });
120
+ const hasRemainingInvoices = checkData.invoices?.some(inv => inv.currency_id === currencyId);
121
+ if (hasRemainingInvoices) {
122
+ return;
123
+ }
124
+ setStripePaymentInProgress(prev => {
125
+ const newState = {
126
+ ...prev
127
+ };
128
+ delete newState[currencyId];
129
+ return newState;
130
+ });
131
+ setPaymentStatus(prev => ({
132
+ ...prev,
133
+ [currencyId]: "success"
134
+ }));
135
+ } catch (err) {
136
+ console.error("Error checking Stripe payment completion:", err);
137
+ return;
138
+ }
139
+ }
107
140
  if (successToast) {
108
141
  _Toast.default.close();
109
142
  _Toast.default.success(t("payment.customer.invoice.paySuccess"));
@@ -133,7 +166,7 @@ function OverdueInvoicePayment({
133
166
  });
134
167
  return isPaid;
135
168
  };
136
- const handleConnected = async () => {
169
+ const handleConnected = async (currencyId, isStripe = false) => {
137
170
  if (isCrossOriginRequest) {
138
171
  try {
139
172
  const paid = await waitForInvoiceAllPaid();
@@ -143,31 +176,45 @@ function OverdueInvoicePayment({
143
176
  }
144
177
  if (paid) {
145
178
  setDialogOpen(false);
146
- onPaid(sourceId, selectCurrencyId, sourceType);
179
+ onPaid(sourceId, currencyId, sourceType);
147
180
  }
148
181
  } catch (err) {
149
182
  console.error("Check payment status failed:", err);
150
183
  }
184
+ } else if (isStripe) {
185
+ setStripePaymentInProgress(prev => ({
186
+ ...prev,
187
+ [currencyId]: true
188
+ }));
189
+ setPaymentStatus(prev => ({
190
+ ...prev,
191
+ [currencyId]: "processing"
192
+ }));
151
193
  }
152
194
  };
153
195
  (0, _react.useEffect)(() => {
154
- if (subscription && !isCrossOriginRequest) {
155
- subscription.on("invoice.paid", ({
156
- response
157
- }) => {
158
- const relevantId = subscriptionId || response.customer_id;
159
- const uniqueKey = `${relevantId}-${response.currency_id}`;
160
- if (subscriptionId && response.subscription_id === subscriptionId || effectiveCustomerId && effectiveCustomerId === response.customer_id || customerIdRef.current && customerIdRef.current === response.customer_id) {
161
- if (!processedCurrencies[uniqueKey]) {
162
- setProcessedCurrencies(prev => ({
163
- ...prev,
164
- [uniqueKey]: 1
165
- }));
166
- debouncedHandleInvoicePaid(response.currency_id);
167
- }
168
- }
169
- });
196
+ if (!subscription || isCrossOriginRequest) {
197
+ return void 0;
170
198
  }
199
+ const handleInvoicePaid = ({
200
+ response
201
+ }) => {
202
+ const relevantId = subscriptionId || response.customer_id;
203
+ const uniqueKey = `${relevantId}-${response.currency_id}`;
204
+ if (subscriptionId && response.subscription_id === subscriptionId || effectiveCustomerId && effectiveCustomerId === response.customer_id || customerIdRef.current && customerIdRef.current === response.customer_id) {
205
+ if (!processedCurrencies[uniqueKey]) {
206
+ setProcessedCurrencies(prev => ({
207
+ ...prev,
208
+ [uniqueKey]: 1
209
+ }));
210
+ debouncedHandleInvoicePaid(response.currency_id);
211
+ }
212
+ }
213
+ };
214
+ subscription.on("invoice.paid", handleInvoicePaid);
215
+ return () => {
216
+ subscription.off("invoice.paid", handleInvoicePaid);
217
+ };
171
218
  }, [subscription, subscriptionId, effectiveCustomerId]);
172
219
  const handlePay = item => {
173
220
  const {
@@ -211,7 +258,7 @@ function OverdueInvoicePayment({
211
258
  },
212
259
  onSuccess: () => {
213
260
  connect.close();
214
- handleConnected();
261
+ handleConnected(currency.id);
215
262
  setPayLoading(false);
216
263
  setPaymentStatus(prev => ({
217
264
  ...prev,
@@ -258,7 +305,7 @@ function OverdueInvoicePayment({
258
305
  }
259
306
  return t("payment.customer.pastDue.view");
260
307
  };
261
- const renderPayButton = (item, primaryButton = true, props = {
308
+ const renderPayButton = (item, primaryButton = true, options = {
262
309
  variant: "contained"
263
310
  }) => {
264
311
  const {
@@ -268,7 +315,7 @@ function OverdueInvoicePayment({
268
315
  const status = paymentStatus[currency.id] || "idle";
269
316
  if (status === "success") {
270
317
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
271
- variant: props?.variant || "contained",
318
+ variant: options?.variant || "contained",
272
319
  size: "small",
273
320
  ...(primaryButton ? {} : {
274
321
  color: "success",
@@ -279,29 +326,50 @@ function OverdueInvoicePayment({
279
326
  }
280
327
  if (status === "error") {
281
328
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
282
- variant: "contained",
329
+ variant: options?.variant || "contained",
283
330
  size: "small",
284
331
  onClick: () => handlePay(item),
285
- ...props,
332
+ sx: options?.sx,
286
333
  children: t("payment.subscription.overdue.retry")
287
334
  });
288
335
  }
289
336
  if (item.method.type === "stripe") {
290
- return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
291
- variant: "contained",
292
- color: "primary",
293
- onClick: () => window.open(detailUrl, "_blank"),
294
- ...props,
295
- children: t("payment.subscription.overdue.viewNow")
337
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, {
338
+ subscriptionId,
339
+ customerId: !subscriptionId ? effectiveCustomerId : void 0,
340
+ currencyId: currency.id,
341
+ paymentMethod: item.method,
342
+ onSuccess: () => {
343
+ handleConnected(currency.id, true);
344
+ },
345
+ onError: () => {
346
+ setPaymentStatus(prev => ({
347
+ ...prev,
348
+ [currency.id]: "error"
349
+ }));
350
+ setStripePaymentInProgress(prev => ({
351
+ ...prev,
352
+ [currency.id]: false
353
+ }));
354
+ },
355
+ children: (onPay, paying) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
356
+ variant: options?.variant || "contained",
357
+ size: "small",
358
+ disabled: paying || status === "processing",
359
+ loading: paying || status === "processing",
360
+ onClick: onPay,
361
+ sx: options?.sx,
362
+ children: status === "processing" ? t("payment.subscription.overdue.processing") : t("payment.subscription.overdue.payNow")
363
+ })
296
364
  });
297
365
  }
298
366
  return /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
299
- variant: "contained",
367
+ variant: options?.variant || "contained",
300
368
  size: "small",
301
369
  disabled: inProcess,
302
370
  loading: inProcess,
303
371
  onClick: () => handlePay(item),
304
- ...props,
372
+ sx: options?.sx,
305
373
  children: t("payment.subscription.overdue.payNow")
306
374
  });
307
375
  };
@@ -17,7 +17,8 @@ function PaymentBeneficiaries({
17
17
  totalAmount = "0"
18
18
  }) {
19
19
  const {
20
- t
20
+ t,
21
+ locale
21
22
  } = (0, _context.useLocaleContext)();
22
23
  return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
23
24
  spacing: 2,
@@ -66,7 +67,7 @@ function PaymentBeneficiaries({
66
67
  variant: "subtitle2",
67
68
  onClick: () => {
68
69
  if (item.url) {
69
- window.open(item.url, "_blank");
70
+ window.open((0, _util2.formatLinkWithLocale)(item.url, locale), "_blank");
70
71
  }
71
72
  },
72
73
  sx: {
@@ -0,0 +1,16 @@
1
+ import type { TPaymentMethod, TInvoiceExpanded } from '@blocklet/payment-types';
2
+ export interface StripePaymentActionProps {
3
+ invoice?: TInvoiceExpanded;
4
+ invoiceIds?: string[];
5
+ subscriptionId?: string;
6
+ customerId?: string;
7
+ currencyId?: string;
8
+ paymentMethod?: TPaymentMethod;
9
+ autoTrigger?: boolean;
10
+ onExternalPayment?: (invoiceId?: string) => void;
11
+ onSuccess?: () => void;
12
+ onError?: (error: Error) => void;
13
+ onClose?: () => void;
14
+ children?: (onPay: () => void, loading: boolean) => React.ReactNode;
15
+ }
16
+ export default function StripePaymentAction(props: StripePaymentActionProps): import("react").JSX.Element;
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = StripePaymentAction;
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ var _context = require("@arcblock/ux/lib/Locale/context");
9
+ var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
10
+ var _ux = require("@arcblock/ux");
11
+ var _material = require("@mui/material");
12
+ var _ahooks = require("ahooks");
13
+ var _react = require("react");
14
+ var _stripe = _interopRequireDefault(require("../payment/form/stripe"));
15
+ var _api = _interopRequireDefault(require("../libs/api"));
16
+ var _util = require("../libs/util");
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ function StripePaymentAction(props) {
19
+ const {
20
+ invoice,
21
+ invoiceIds,
22
+ subscriptionId,
23
+ customerId,
24
+ currencyId,
25
+ paymentMethod,
26
+ autoTrigger = false,
27
+ onExternalPayment,
28
+ onSuccess,
29
+ onError,
30
+ onClose,
31
+ children
32
+ } = props;
33
+ const {
34
+ t
35
+ } = (0, _context.useLocaleContext)();
36
+ const [state, setState] = (0, _ahooks.useSetState)({
37
+ paying: false,
38
+ confirmDialog: false,
39
+ stripeDialog: false,
40
+ clientSecret: null,
41
+ publishableKey: null,
42
+ customer: null
43
+ });
44
+ const autoTriggerRef = (0, _react.useRef)(false);
45
+ (0, _react.useEffect)(() => {
46
+ if (autoTrigger && !autoTriggerRef.current) {
47
+ autoTriggerRef.current = true;
48
+ handlePay();
49
+ }
50
+ }, [autoTrigger]);
51
+ const handlePay = async () => {
52
+ if (state.paying) {
53
+ return;
54
+ }
55
+ const hasSubscription = !!(subscriptionId || invoice?.subscription_id);
56
+ const method = paymentMethod || invoice?.paymentMethod;
57
+ const shouldShowConfirm = hasSubscription && method?.type === "stripe";
58
+ if (shouldShowConfirm) {
59
+ setState({
60
+ confirmDialog: true
61
+ });
62
+ return;
63
+ }
64
+ await proceedWithPayment();
65
+ };
66
+ const proceedWithPayment = async () => {
67
+ setState({
68
+ paying: true,
69
+ confirmDialog: false
70
+ });
71
+ const derivedCurrencyId = currencyId || invoice?.currency_id || invoice?.paymentCurrency?.id;
72
+ const derivedPaymentMethod = paymentMethod || invoice?.paymentMethod;
73
+ const isStripePayment = derivedPaymentMethod?.type === "stripe";
74
+ if (isStripePayment && derivedCurrencyId) {
75
+ const stripePayload = {};
76
+ if (invoiceIds && invoiceIds.length > 0) {
77
+ stripePayload.invoice_ids = invoiceIds;
78
+ } else if (invoice) {
79
+ stripePayload.invoice_ids = [invoice.id];
80
+ } else if (subscriptionId) {
81
+ stripePayload.subscription_id = subscriptionId;
82
+ } else if (customerId) {
83
+ stripePayload.customer_id = customerId;
84
+ }
85
+ if (derivedCurrencyId) {
86
+ stripePayload.currency_id = derivedCurrencyId;
87
+ }
88
+ try {
89
+ const {
90
+ data: paymentData
91
+ } = await _api.default.post("/api/invoices/pay-stripe", stripePayload);
92
+ setState({
93
+ paying: false,
94
+ stripeDialog: true,
95
+ clientSecret: paymentData.client_secret,
96
+ publishableKey: paymentData.publishable_key,
97
+ customer: paymentData.customer || null
98
+ });
99
+ return;
100
+ } catch (err) {
101
+ const error = (0, _util.formatError)(err);
102
+ _Toast.default.error(error);
103
+ setState({
104
+ paying: false
105
+ });
106
+ onError?.(error);
107
+ return;
108
+ }
109
+ }
110
+ setState({
111
+ paying: false
112
+ });
113
+ if (onExternalPayment) {
114
+ onExternalPayment(invoice?.id);
115
+ return;
116
+ }
117
+ _Toast.default.error(t("payment.customer.invoice.payError"));
118
+ onError?.(new Error("EXTERNAL_PAYMENT_HANDLER_NOT_PROVIDED"));
119
+ };
120
+ const handleConfirmCancel = () => {
121
+ setState({
122
+ confirmDialog: false,
123
+ paying: false
124
+ });
125
+ onClose?.();
126
+ };
127
+ const handleStripeConfirm = () => {
128
+ _Toast.default.success(t("payment.customer.invoice.payProcessing"));
129
+ setState({
130
+ paying: false,
131
+ stripeDialog: false,
132
+ clientSecret: null,
133
+ publishableKey: null,
134
+ customer: null
135
+ });
136
+ setTimeout(() => {
137
+ onSuccess?.();
138
+ }, 2e3);
139
+ };
140
+ const handleStripeCancel = () => {
141
+ setState({
142
+ paying: false,
143
+ stripeDialog: false,
144
+ clientSecret: null,
145
+ publishableKey: null,
146
+ customer: null
147
+ });
148
+ onClose?.();
149
+ };
150
+ return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
151
+ children: [children?.(handlePay, state.paying), state.confirmDialog && /* @__PURE__ */(0, _jsxRuntime.jsx)(_ux.Dialog, {
152
+ open: state.confirmDialog,
153
+ title: t("payment.customer.invoice.paymentConfirmTitle"),
154
+ onClose: handleConfirmCancel,
155
+ maxWidth: "sm",
156
+ PaperProps: {
157
+ style: {
158
+ minHeight: 0
159
+ }
160
+ },
161
+ actions: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
162
+ variant: "outlined",
163
+ onClick: handleConfirmCancel,
164
+ children: t("common.cancel")
165
+ }, "cancel"), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
166
+ variant: "contained",
167
+ onClick: proceedWithPayment,
168
+ children: t("payment.customer.invoice.continue")
169
+ }, "continue")],
170
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
171
+ variant: "body1",
172
+ sx: {
173
+ color: "text.secondary",
174
+ mt: -2
175
+ },
176
+ children: t("payment.customer.invoice.paymentConfirmDescription")
177
+ })
178
+ }), state.stripeDialog && state.clientSecret && state.publishableKey && state.customer && /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripe.default, {
179
+ clientSecret: state.clientSecret,
180
+ intentType: "setup_intent",
181
+ publicKey: state.publishableKey,
182
+ customer: state.customer,
183
+ mode: "setup",
184
+ title: t("payment.customer.invoice.pay"),
185
+ submitButtonText: t("common.submit"),
186
+ onConfirm: handleStripeConfirm,
187
+ onCancel: handleStripeCancel,
188
+ returnUrl: window.location.href
189
+ })]
190
+ });
191
+ }
@@ -18,6 +18,7 @@ var _status = _interopRequireDefault(require("../../components/status"));
18
18
  var _payment = require("../../contexts/payment");
19
19
  var _subscription = require("../../hooks/subscription");
20
20
  var _api = _interopRequireDefault(require("../../libs/api"));
21
+ var _stripePaymentAction = _interopRequireDefault(require("../../components/stripe-payment-action"));
21
22
  var _util = require("../../libs/util");
22
23
  var _table = _interopRequireDefault(require("../../components/table"));
23
24
  var _navigation = require("../../libs/navigation");
@@ -282,15 +283,41 @@ const InvoiceTable = _react.default.memo(props => {
282
283
  } = getInvoiceLink(invoice, action);
283
284
  const isVoid = invoice.status === "void";
284
285
  if (action && !hidePay) {
285
- return connect ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
286
- variant: "text",
287
- size: "small",
288
- onClick: () => onPay(invoice.id),
289
- sx: {
290
- color: "text.link"
291
- },
292
- children: t("payment.customer.invoice.pay")
293
- }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
286
+ if (connect) {
287
+ if (invoice.paymentMethod?.type === "stripe") {
288
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, {
289
+ invoice,
290
+ paymentMethod: invoice.paymentMethod,
291
+ onSuccess: () => {
292
+ refresh();
293
+ },
294
+ children: (handlePay, paying) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
295
+ variant: "text",
296
+ size: "small",
297
+ sx: {
298
+ color: "text.link"
299
+ },
300
+ disabled: paying,
301
+ onClick: e => {
302
+ e.preventDefault();
303
+ e.stopPropagation();
304
+ handlePay();
305
+ },
306
+ children: paying ? t("payment.checkout.processing") : t("payment.customer.invoice.pay")
307
+ })
308
+ });
309
+ }
310
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
311
+ variant: "text",
312
+ size: "small",
313
+ onClick: () => onPay(invoice.id),
314
+ sx: {
315
+ color: "text.link"
316
+ },
317
+ children: t("payment.customer.invoice.pay")
318
+ });
319
+ }
320
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
294
321
  component: "a",
295
322
  variant: "text",
296
323
  size: "small",
@@ -580,7 +607,28 @@ const InvoiceList = _react.default.memo(props => {
580
607
  flex: 1,
581
608
  textAlign: "right"
582
609
  },
583
- children: action ? connect ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
610
+ children: action ? connect ? invoice.paymentMethod?.type === "stripe" ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, {
611
+ invoice,
612
+ paymentMethod: invoice.paymentMethod,
613
+ onSuccess: async () => {
614
+ await reloadAsync();
615
+ },
616
+ children: (handlePay, paying) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
617
+ variant: "contained",
618
+ color: "primary",
619
+ size: "small",
620
+ sx: {
621
+ whiteSpace: "nowrap"
622
+ },
623
+ disabled: paying,
624
+ onClick: e => {
625
+ e.preventDefault();
626
+ e.stopPropagation();
627
+ handlePay();
628
+ },
629
+ children: paying ? t("payment.checkout.processing") : t("payment.customer.invoice.pay")
630
+ })
631
+ }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
584
632
  variant: "contained",
585
633
  color: "primary",
586
634
  size: "small",
package/lib/index.d.ts CHANGED
@@ -32,6 +32,7 @@ import TruncatedText from './components/truncated-text';
32
32
  import Link from './components/link';
33
33
  import { createLazyComponent } from './components/lazy-loader';
34
34
  import OverdueInvoicePayment from './components/over-due-invoice-payment';
35
+ import StripePaymentAction from './components/stripe-payment-action';
35
36
  import PaymentBeneficiaries from './components/payment-beneficiaries';
36
37
  import LoadingButton from './components/loading-button';
37
38
  import ResumeSubscription from './components/resume-subscription';
@@ -55,5 +56,6 @@ export * from './hooks/scroll';
55
56
  export * from './hooks/keyboard';
56
57
  export * from './libs/validator';
57
58
  export { translations, createTranslator } from './locales';
58
- export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, PromotionCode, SourceDataViewer, };
59
+ export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, StripePaymentAction, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, PromotionCode, SourceDataViewer, };
59
60
  export type { CountrySelectProps } from './components/country-select';
61
+ export type { StripePaymentActionProps } from './components/stripe-payment-action';
package/lib/index.js CHANGED
@@ -40,6 +40,7 @@ var _exportNames = {
40
40
  Link: true,
41
41
  createLazyComponent: true,
42
42
  OverdueInvoicePayment: true,
43
+ StripePaymentAction: true,
43
44
  PaymentBeneficiaries: true,
44
45
  LoadingButton: true,
45
46
  ResumeSubscription: true,
@@ -281,6 +282,12 @@ Object.defineProperty(exports, "StripeForm", {
281
282
  return _stripe.default;
282
283
  }
283
284
  });
285
+ Object.defineProperty(exports, "StripePaymentAction", {
286
+ enumerable: true,
287
+ get: function () {
288
+ return _stripePaymentAction.default;
289
+ }
290
+ });
284
291
  Object.defineProperty(exports, "Switch", {
285
292
  enumerable: true,
286
293
  get: function () {
@@ -375,6 +382,7 @@ var _truncatedText = _interopRequireDefault(require("./components/truncated-text
375
382
  var _link = _interopRequireDefault(require("./components/link"));
376
383
  var _lazyLoader = require("./components/lazy-loader");
377
384
  var _overDueInvoicePayment = _interopRequireDefault(require("./components/over-due-invoice-payment"));
385
+ var _stripePaymentAction = _interopRequireDefault(require("./components/stripe-payment-action"));
378
386
  var _paymentBeneficiaries = _interopRequireDefault(require("./components/payment-beneficiaries"));
379
387
  var _loadingButton = _interopRequireDefault(require("./components/loading-button"));
380
388
  var _resumeSubscription = _interopRequireDefault(require("./components/resume-subscription"));
@@ -135,3 +135,4 @@ export declare function parseMarkedText(text: string): Array<{
135
135
  export declare function getTokenBalanceLink(method: TPaymentMethod, address: string): string;
136
136
  export declare function isCreditMetered(price: TPrice): boolean;
137
137
  export declare function showStaking(method: TPaymentMethod, currency: TPaymentCurrency, noStake: boolean): boolean;
138
+ export declare function formatLinkWithLocale(url: string, locale?: string): string;
package/lib/libs/util.js CHANGED
@@ -14,6 +14,7 @@ exports.formatCouponTerms = void 0;
14
14
  exports.formatDateTime = formatDateTime;
15
15
  exports.formatError = void 0;
16
16
  exports.formatLineItemPricing = formatLineItemPricing;
17
+ exports.formatLinkWithLocale = formatLinkWithLocale;
17
18
  exports.formatLocale = void 0;
18
19
  exports.formatMeteredThen = formatMeteredThen;
19
20
  exports.formatNumber = formatNumber;
@@ -1278,4 +1279,20 @@ function showStaking(method, currency, noStake) {
1278
1279
  return currency.type !== "credit";
1279
1280
  }
1280
1281
  return false;
1282
+ }
1283
+ function formatLinkWithLocale(url, locale) {
1284
+ if (!locale || !url) {
1285
+ return url;
1286
+ }
1287
+ try {
1288
+ const urlObj = new URL(url);
1289
+ urlObj.searchParams.set("locale", locale);
1290
+ return urlObj.toString();
1291
+ } catch (error) {
1292
+ if (/[?&]locale=[^&]*/.test(url)) {
1293
+ return url.replace(/([?&])locale=[^&]*/, `$1locale=${locale}`);
1294
+ }
1295
+ const separator = url.includes("?") ? "&" : "?";
1296
+ return `${url}${separator}locale=${locale}`;
1297
+ }
1281
1298
  }