w-aura/src/components/PaymentPage/methods/ExpressCheckoutStripe/index.tsx
Денис Катаев d8da6d9de6 AW-104-express-checkout
2024-06-12 23:15:41 +00:00

117 lines
3.5 KiB
TypeScript

import { useMemo, useState } from "react";
import styles from "./styles.module.css";
import {
useStripe,
useElements,
ExpressCheckoutElement,
} from "@stripe/react-stripe-js";
import {
AvailablePaymentMethods,
StripeExpressCheckoutElementReadyEvent,
} from "@stripe/stripe-js";
interface IExpressCheckoutStripeProps {
clientSecret: string;
returnUrl?: string;
isHide?: boolean;
onAvailable?: (
isAvailable: boolean,
availableMethods: AvailablePaymentMethods | undefined
) => void;
onChangeLoading?: (isLoading: boolean) => void;
}
const checkFormAvailable = (
availablePaymentMethods: undefined | AvailablePaymentMethods
) => {
if (!availablePaymentMethods) return false;
let result = false;
for (const key in availablePaymentMethods) {
if (availablePaymentMethods[key as keyof AvailablePaymentMethods]) {
result = true;
break;
}
}
return result;
};
function ExpressCheckoutStripe({
clientSecret,
returnUrl = "https://${window.location.host}/payment/result/",
isHide = false,
onAvailable,
onChangeLoading,
}: IExpressCheckoutStripeProps) {
const stripe = useStripe();
const elements = useElements();
const [errorMessage, setErrorMessage] = useState<string>();
const [isAvailable, setIsAvailable] = useState(false);
const isHideForm = useMemo(
() => isHide || !isAvailable,
[isAvailable, isHide]
);
const onConfirm = async () =>
// event: StripeExpressCheckoutElementConfirmEvent
{
if (!stripe || !elements) {
// Stripe.js hasn't loaded yet.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
const { error: submitError } = await elements.submit();
if (submitError) {
setErrorMessage(submitError.message);
return;
}
// // Create the PaymentIntent and obtain clientSecret
// const res = await fetch("/create-intent", {
// method: "POST",
// });
// const { client_secret: clientSecret } = await res.json();
// Confirm the PaymentIntent using the details collected by the Express Checkout Element
const { error } = await stripe.confirmPayment({
// `elements` instance used to create the Express Checkout Element
elements,
// `clientSecret` from the created PaymentIntent
clientSecret,
confirmParams: {
return_url: returnUrl,
},
});
if (error) {
// This point is only reached if there's an immediate error when
// confirming the payment. Show the error to your customer (for example, payment details incomplete)
setErrorMessage(error.message);
} else {
// The payment UI automatically closes with a success animation.
// Your customer is redirected to your `return_url`.
}
};
const onReady = (event: StripeExpressCheckoutElementReadyEvent) => {
const _isAvailable = checkFormAvailable(event.availablePaymentMethods);
setIsAvailable(_isAvailable);
onAvailable && onAvailable(_isAvailable, event.availablePaymentMethods);
onChangeLoading && onChangeLoading(false);
};
return (
<div className={`${styles.container} ${isHideForm ? styles.hide : ""}`}>
<ExpressCheckoutElement
onReady={onReady}
onLoadError={() => onChangeLoading && onChangeLoading(false)}
onConfirm={onConfirm}
/>
{errorMessage && <p className={styles.error}>{errorMessage}</p>}
</div>
);
}
export default ExpressCheckoutStripe;