@blocklet/payment-react
Version:
Reusable react components for payment kit v2
165 lines (164 loc) • 5.37 kB
JavaScript
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
import Toast from "@arcblock/ux/lib/Toast";
import { Dialog } from "@arcblock/ux";
import { Button, Typography } from "@mui/material";
import { useSetState } from "ahooks";
import { useEffect, useRef } from "react";
import StripeForm from "../payment/form/stripe/index.js";
import api from "../libs/api.js";
import { formatError } from "../libs/util.js";
export default function StripePaymentAction(props) {
const {
invoice,
invoiceIds,
subscriptionId,
customerId,
currencyId,
paymentMethod,
autoTrigger = false,
onExternalPayment,
onSuccess,
onError,
onClose,
children
} = props;
const { t } = useLocaleContext();
const [state, setState] = useSetState({
paying: false,
confirmDialog: false,
stripeDialog: false,
clientSecret: null,
publishableKey: null,
customer: null
});
const autoTriggerRef = useRef(false);
useEffect(() => {
if (autoTrigger && !autoTriggerRef.current) {
autoTriggerRef.current = true;
handlePay();
}
}, [autoTrigger]);
const handlePay = async () => {
if (state.paying) {
return;
}
const hasSubscription = !!(subscriptionId || invoice?.subscription_id);
const method = paymentMethod || invoice?.paymentMethod;
const shouldShowConfirm = hasSubscription && method?.type === "stripe";
if (shouldShowConfirm) {
setState({ confirmDialog: true });
return;
}
await proceedWithPayment();
};
const proceedWithPayment = async () => {
setState({ paying: true, confirmDialog: false });
const derivedCurrencyId = currencyId || invoice?.currency_id || invoice?.paymentCurrency?.id;
const derivedPaymentMethod = paymentMethod || invoice?.paymentMethod;
const isStripePayment = derivedPaymentMethod?.type === "stripe";
if (isStripePayment && derivedCurrencyId) {
const stripePayload = {};
if (invoiceIds && invoiceIds.length > 0) {
stripePayload.invoice_ids = invoiceIds;
} else if (invoice) {
stripePayload.invoice_ids = [invoice.id];
} else if (subscriptionId) {
stripePayload.subscription_id = subscriptionId;
} else if (customerId) {
stripePayload.customer_id = customerId;
}
if (derivedCurrencyId) {
stripePayload.currency_id = derivedCurrencyId;
}
try {
const { data: paymentData } = await api.post("/api/invoices/pay-stripe", stripePayload);
setState({
paying: false,
stripeDialog: true,
clientSecret: paymentData.client_secret,
publishableKey: paymentData.publishable_key,
customer: paymentData.customer || null
});
return;
} catch (err) {
const error = formatError(err);
Toast.error(error);
setState({ paying: false });
onError?.(error);
return;
}
}
setState({ paying: false });
if (onExternalPayment) {
onExternalPayment(invoice?.id);
return;
}
Toast.error(t("payment.customer.invoice.payError"));
onError?.(new Error("EXTERNAL_PAYMENT_HANDLER_NOT_PROVIDED"));
};
const handleConfirmCancel = () => {
setState({ confirmDialog: false, paying: false });
onClose?.();
};
const handleStripeConfirm = () => {
Toast.success(t("payment.customer.invoice.payProcessing"));
setState({
paying: false,
stripeDialog: false,
clientSecret: null,
publishableKey: null,
customer: null
});
setTimeout(() => {
onSuccess?.();
}, 2e3);
};
const handleStripeCancel = () => {
setState({
paying: false,
stripeDialog: false,
clientSecret: null,
publishableKey: null,
customer: null
});
onClose?.();
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
children?.(handlePay, state.paying),
state.confirmDialog && /* @__PURE__ */ jsx(
Dialog,
{
open: state.confirmDialog,
title: t("payment.customer.invoice.paymentConfirmTitle"),
onClose: handleConfirmCancel,
maxWidth: "sm",
PaperProps: {
style: {
minHeight: 0
}
},
actions: [
/* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: handleConfirmCancel, children: t("common.cancel") }, "cancel"),
/* @__PURE__ */ jsx(Button, { variant: "contained", onClick: proceedWithPayment, children: t("payment.customer.invoice.continue") }, "continue")
],
children: /* @__PURE__ */ jsx(Typography, { variant: "body1", sx: { color: "text.secondary", mt: -2 }, children: t("payment.customer.invoice.paymentConfirmDescription") })
}
),
state.stripeDialog && state.clientSecret && state.publishableKey && state.customer && /* @__PURE__ */ jsx(
StripeForm,
{
clientSecret: state.clientSecret,
intentType: "setup_intent",
publicKey: state.publishableKey,
customer: state.customer,
mode: "setup",
title: t("payment.customer.invoice.pay"),
submitButtonText: t("common.submit"),
onConfirm: handleStripeConfirm,
onCancel: handleStripeCancel,
returnUrl: window.location.href
}
)
] });
}