w-aura/src/components/StripePage/ApplePayButton/index.tsx
2024-05-20 14:24:53 +00:00

122 lines
3.1 KiB
TypeScript

import { useEffect, useState } from "react";
import {
PaymentRequestButtonElement,
useStripe,
useElements,
} from "@stripe/react-stripe-js";
import { PaymentRequest } from "@stripe/stripe-js";
import styles from "./styles.module.css";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { IPaywallProduct } from "@/api/resources/Paywall";
interface ApplePayButtonProps {
activeProduct: IPaywallProduct | null;
client_secret: string;
subscriptionReceiptId?: string;
returnUrl?: string;
setCanMakePayment?: (isCanMakePayment: boolean) => void;
}
function ApplePayButton({
activeProduct,
client_secret,
subscriptionReceiptId,
returnUrl,
setCanMakePayment,
}: ApplePayButtonProps) {
const stripe = useStripe();
const elements = useElements();
const dispatch = useDispatch();
const navigate = useNavigate();
const [paymentRequest, setPaymentRequest] = useState<PaymentRequest | null>(
null
);
const getAmountFromProduct = (subPlan: IPaywallProduct) => {
if (subPlan.isTrial) {
return subPlan.trialPrice;
}
return subPlan.price;
};
useEffect(() => {
if (!stripe || !elements || !activeProduct) {
return;
}
const pr = stripe.paymentRequest({
country: "US",
currency: "usd",
total: {
label: activeProduct.name || "Subscription",
amount: getAmountFromProduct(activeProduct),
},
requestPayerName: true,
requestPayerEmail: true,
});
pr.canMakePayment().then((result) => {
if (result) {
setPaymentRequest(pr);
setCanMakePayment?.(true);
}
});
pr.on("paymentmethod", async (e) => {
const { error: stripeError, paymentIntent } =
await stripe.confirmCardPayment(
client_secret,
{
payment_method: e.paymentMethod.id,
},
{ handleActions: false }
);
paymentIntent;
if (stripeError) {
// Show error to your customer (e.g., insufficient funds)
navigate(
`${routes.client.paymentResult()}/${subscriptionReceiptId}/?redirect_status=failed`
);
return e.complete("fail");
}
navigate(
returnUrl ||
`${routes.client.paymentResult()}/${subscriptionReceiptId}/?redirect_status=succeeded`
);
e.complete("success");
// Show a success message to your customer
// There's a risk of the customer closing the window before callback
// execution. Set up a webhook or plugin to listen for the
// payment_intent.succeeded event that handles any business critical
// post-payment actions.
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
client_secret,
dispatch,
elements,
navigate,
stripe,
subscriptionReceiptId,
]);
return (
<>
{paymentRequest && (
<PaymentRequestButtonElement
className={styles["stripe-element"]}
options={{
paymentRequest,
style: { paymentRequestButton: { height: "60px" } },
}}
/>
)}
</>
);
}
export default ApplePayButton;