AW-104-express-checkout
This commit is contained in:
parent
fb00697993
commit
d8da6d9de6
BIN
public/amazon-pay-mark.png
Normal file
BIN
public/amazon-pay-mark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,116 @@
|
|||||||
|
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;
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
width: 100%;
|
||||||
|
color: #FF5758;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
import { Elements } from "@stripe/react-stripe-js";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
import { AvailablePaymentMethods, Stripe, loadStripe } from "@stripe/stripe-js";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@ -15,8 +15,7 @@ import SecurityPayments from "../SecurityPayments";
|
|||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
||||||
import StripeButton from "@/components/PaymentPage/methods/StripeButton";
|
import ExpressCheckoutStripe from "@/components/PaymentPage/methods/ExpressCheckoutStripe";
|
||||||
import CheckAvailableStripeButton from "@/components/PaymentPage/methods/StripeButton/CheckAvailableStripeButton";
|
|
||||||
|
|
||||||
interface IPaymentModalProps {
|
interface IPaymentModalProps {
|
||||||
activeProduct?: IPaywallProduct;
|
activeProduct?: IPaywallProduct;
|
||||||
@ -49,7 +48,7 @@ function PaymentModal({
|
|||||||
returnUrl: checkoutUrl,
|
returnUrl: checkoutUrl,
|
||||||
paymentType,
|
paymentType,
|
||||||
publicKey,
|
publicKey,
|
||||||
isLoading,
|
isLoading: isLoadingPayment,
|
||||||
error,
|
error,
|
||||||
} = useMakePayment({
|
} = useMakePayment({
|
||||||
productId: _activeProduct?._id || "",
|
productId: _activeProduct?._id || "",
|
||||||
@ -58,17 +57,23 @@ function PaymentModal({
|
|||||||
returnPaidUrl: returnUrl,
|
returnPaidUrl: returnUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
const stripeButton = useSelector(selectors.selectStripeButton);
|
const [availableMethods, setAvailableMethods] = useState<
|
||||||
|
AvailablePaymentMethods | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
const paymentRequest = stripeButton?.paymentRequest;
|
const [isLoadingExpressCheckout, setIsLoadingExpressCheckout] =
|
||||||
const availableMethods = stripeButton?.availableMethods;
|
useState(true);
|
||||||
|
|
||||||
|
const isLoading = useMemo(() => {
|
||||||
|
return isLoadingPayment || isLoadingExpressCheckout;
|
||||||
|
}, [isLoadingPayment, isLoadingExpressCheckout]);
|
||||||
|
|
||||||
if (checkoutUrl?.length) {
|
if (checkoutUrl?.length) {
|
||||||
window.location.href = checkoutUrl;
|
window.location.href = checkoutUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const paymentMethodsButtons = useMemo(() => {
|
const paymentMethodsButtons = useMemo(() => {
|
||||||
return paymentMethods(availableMethods);
|
return paymentMethods(availableMethods || null);
|
||||||
}, [availableMethods]);
|
}, [availableMethods]);
|
||||||
|
|
||||||
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(
|
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(
|
||||||
@ -92,15 +97,16 @@ function PaymentModal({
|
|||||||
})();
|
})();
|
||||||
}, [_activeProduct, navigate, products, publicKey]);
|
}, [_activeProduct, navigate, products, publicKey]);
|
||||||
|
|
||||||
if (isLoading) {
|
const onAvailableExpressCheckout = (
|
||||||
return (
|
isAvailable: boolean,
|
||||||
<div className={styles["payment-modal"]}>
|
availableMethods: AvailablePaymentMethods | undefined
|
||||||
<div className={styles["payment-loader"]}>
|
) => {
|
||||||
<Loader />
|
if (isAvailable && availableMethods) {
|
||||||
</div>
|
setAvailableMethods(availableMethods);
|
||||||
</div>
|
return setSelectedPaymentMethod(EPaymentMethod.PAYMENT_BUTTONS);
|
||||||
);
|
}
|
||||||
}
|
return setAvailableMethods(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
if (error?.length) {
|
if (error?.length) {
|
||||||
return (
|
return (
|
||||||
@ -113,62 +119,75 @@ function PaymentModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["payment-modal"]}>
|
<>
|
||||||
<Title variant="h3" className={styles.title}>
|
{isLoading && (
|
||||||
Choose payment method
|
<div className={styles["payment-modal"]}>
|
||||||
</Title>
|
<div className={styles["payment-loader"]}>
|
||||||
<PaymentMethodsChoice
|
<Loader />
|
||||||
paymentMethods={paymentMethodsButtons}
|
</div>
|
||||||
selectedPaymentMethod={selectedPaymentMethod}
|
|
||||||
onSelectPaymentMethod={onSelectPaymentMethod}
|
|
||||||
/>
|
|
||||||
{_activeProduct && (
|
|
||||||
<div>
|
|
||||||
{!noTrial && (
|
|
||||||
<>
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
You will be charged only{" "}
|
|
||||||
<b>${getPrice(_activeProduct)} for your 3-day trial.</b>
|
|
||||||
</p>
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
We`ll <b>email you a reminder</b> before your trial period ends.
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
Cancel anytime. The charge will appear on your bill as witapps.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles["payment-method-container"]}>
|
<div
|
||||||
{stripePromise && clientSecret && (
|
className={`${styles["payment-modal"]} ${isLoading ? styles.hide : ""}`}
|
||||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
>
|
||||||
<CheckAvailableStripeButton
|
<Title variant="h3" className={styles.title}>
|
||||||
activeProduct={_activeProduct}
|
Choose payment method
|
||||||
clientSecret={clientSecret}
|
</Title>
|
||||||
/>
|
<PaymentMethodsChoice
|
||||||
{selectedPaymentMethod === EPaymentMethod.PAYMENT_BUTTONS && (
|
paymentMethods={paymentMethodsButtons}
|
||||||
<div className={styles["payment-method"]}>
|
selectedPaymentMethod={selectedPaymentMethod}
|
||||||
{paymentRequest && (
|
onSelectPaymentMethod={onSelectPaymentMethod}
|
||||||
<StripeButton paymentRequest={paymentRequest} />
|
/>
|
||||||
)}
|
{_activeProduct && (
|
||||||
</div>
|
<div>
|
||||||
|
{!noTrial && (
|
||||||
|
<>
|
||||||
|
<p className={styles["sub-plan-description"]}>
|
||||||
|
You will be charged only{" "}
|
||||||
|
<b>${getPrice(_activeProduct)} for your 3-day trial.</b>
|
||||||
|
</p>
|
||||||
|
<p className={styles["sub-plan-description"]}>
|
||||||
|
We`ll <b>email you a reminder</b> before your trial period
|
||||||
|
ends.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectedPaymentMethod === EPaymentMethod.CREDIT_CARD && (
|
<p className={styles["sub-plan-description"]}>
|
||||||
<CheckoutForm
|
Cancel anytime. The charge will appear on your bill as witapps.
|
||||||
confirmType={paymentType}
|
</p>
|
||||||
subscriptionReceiptId={paymentIntentId}
|
</div>
|
||||||
returnUrl={returnUrl}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Elements>
|
|
||||||
)}
|
)}
|
||||||
|
<div className={styles["payment-method-container"]}>
|
||||||
|
{stripePromise && clientSecret && (
|
||||||
|
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
||||||
|
<ExpressCheckoutStripe
|
||||||
|
clientSecret={clientSecret}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
isHide={
|
||||||
|
selectedPaymentMethod !== EPaymentMethod.PAYMENT_BUTTONS
|
||||||
|
}
|
||||||
|
onAvailable={(_isAvailable, _availableMethods) =>
|
||||||
|
onAvailableExpressCheckout(_isAvailable, _availableMethods)
|
||||||
|
}
|
||||||
|
onChangeLoading={(isLoading) =>
|
||||||
|
setIsLoadingExpressCheckout(isLoading)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{selectedPaymentMethod === EPaymentMethod.CREDIT_CARD && (
|
||||||
|
<CheckoutForm
|
||||||
|
confirmType={paymentType}
|
||||||
|
subscriptionReceiptId={paymentIntentId}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Elements>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<SecurityPayments />
|
||||||
|
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
|
||||||
</div>
|
</div>
|
||||||
<SecurityPayments />
|
</>
|
||||||
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,12 @@
|
|||||||
color: #2f2e37;
|
color: #2f2e37;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.payment-modal.hide {
|
||||||
|
min-height: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
import { EPaymentMethod, paymentMethods } from "@/data/paymentMethods";
|
||||||
import { Elements } from "@stripe/react-stripe-js";
|
import { Elements } from "@stripe/react-stripe-js";
|
||||||
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
import CheckoutForm from "@/components/PaymentPage/methods/CheckoutForm";
|
||||||
import { Stripe, loadStripe } from "@stripe/stripe-js";
|
import { AvailablePaymentMethods, Stripe, loadStripe } from "@stripe/stripe-js";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { selectors } from "@/store";
|
||||||
import Loader from "@/components/Loader";
|
import Loader from "@/components/Loader";
|
||||||
@ -13,8 +13,9 @@ import SecurityPayments from "../SecurityPayments";
|
|||||||
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
|
||||||
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
import { usePaywall } from "@/hooks/paywall/usePaywall";
|
||||||
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
import { useMakePayment } from "@/hooks/payment/useMakePayment";
|
||||||
import StripeButton from "@/components/PaymentPage/methods/StripeButton";
|
import ExpressCheckoutStripe from "@/components/PaymentPage/methods/ExpressCheckoutStripe";
|
||||||
import CheckAvailableStripeButton from "@/components/PaymentPage/methods/StripeButton/CheckAvailableStripeButton";
|
import routes from "@/routes";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
interface IPaymentModalProps {
|
interface IPaymentModalProps {
|
||||||
activeProduct?: IPaywallProduct;
|
activeProduct?: IPaywallProduct;
|
||||||
@ -36,6 +37,7 @@ function PaymentModal({
|
|||||||
returnUrl,
|
returnUrl,
|
||||||
placementKey = EPlacementKeys["aura.placement.main"],
|
placementKey = EPlacementKeys["aura.placement.main"],
|
||||||
}: IPaymentModalProps) {
|
}: IPaymentModalProps) {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [stripePromise, setStripePromise] =
|
const [stripePromise, setStripePromise] =
|
||||||
useState<Promise<Stripe | null> | null>(null);
|
useState<Promise<Stripe | null> | null>(null);
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ function PaymentModal({
|
|||||||
returnUrl: checkoutUrl,
|
returnUrl: checkoutUrl,
|
||||||
paymentType,
|
paymentType,
|
||||||
publicKey,
|
publicKey,
|
||||||
isLoading,
|
isLoading: isLoadingPayment,
|
||||||
error,
|
error,
|
||||||
} = useMakePayment({
|
} = useMakePayment({
|
||||||
productId: _activeProduct?._id || "",
|
productId: _activeProduct?._id || "",
|
||||||
@ -60,20 +62,27 @@ function PaymentModal({
|
|||||||
returnPaidUrl: returnUrl,
|
returnPaidUrl: returnUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { paymentRequest, availableMethods } = useSelector(
|
const [availableMethods, setAvailableMethods] = useState<
|
||||||
selectors.selectStripeButton
|
AvailablePaymentMethods | undefined
|
||||||
);
|
>();
|
||||||
|
|
||||||
|
const [isLoadingExpressCheckout, setIsLoadingExpressCheckout] =
|
||||||
|
useState(true);
|
||||||
|
|
||||||
|
const isLoading = useMemo(() => {
|
||||||
|
return isLoadingPayment || isLoadingExpressCheckout;
|
||||||
|
}, [isLoadingPayment, isLoadingExpressCheckout]);
|
||||||
|
|
||||||
if (checkoutUrl?.length) {
|
if (checkoutUrl?.length) {
|
||||||
window.location.href = checkoutUrl;
|
window.location.href = checkoutUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const paymentMethodsButtons = useMemo(() => {
|
const paymentMethodsButtons = useMemo(() => {
|
||||||
return paymentMethods(availableMethods);
|
return paymentMethods(availableMethods || null);
|
||||||
}, [availableMethods]);
|
}, [availableMethods]);
|
||||||
|
|
||||||
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(
|
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(
|
||||||
EPaymentMethod.PAYMENT_BUTTONS
|
paymentMethodsButtons[0].id
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSelectPaymentMethod = (method: EPaymentMethod) => {
|
const onSelectPaymentMethod = (method: EPaymentMethod) => {
|
||||||
@ -84,18 +93,25 @@ function PaymentModal({
|
|||||||
(async () => {
|
(async () => {
|
||||||
if (!products?.length || !publicKey) return;
|
if (!products?.length || !publicKey) return;
|
||||||
setStripePromise(loadStripe(publicKey));
|
setStripePromise(loadStripe(publicKey));
|
||||||
|
const isActiveProduct = products.find(
|
||||||
|
(product) => product._id === _activeProduct?._id
|
||||||
|
);
|
||||||
|
if (!_activeProduct || !isActiveProduct) {
|
||||||
|
navigate(routes.client.trialChoice());
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}, [products, publicKey]);
|
}, [_activeProduct, navigate, products, publicKey]);
|
||||||
|
|
||||||
if (isLoading) {
|
const onAvailableExpressCheckout = (
|
||||||
return (
|
isAvailable: boolean,
|
||||||
<div className={styles["payment-modal"]}>
|
availableMethods: AvailablePaymentMethods | undefined
|
||||||
<div className={styles["payment-loader"]}>
|
) => {
|
||||||
<Loader />
|
if (isAvailable && availableMethods) {
|
||||||
</div>
|
setAvailableMethods(availableMethods);
|
||||||
</div>
|
return setSelectedPaymentMethod(EPaymentMethod.PAYMENT_BUTTONS);
|
||||||
);
|
}
|
||||||
}
|
return setAvailableMethods(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
if (error?.length) {
|
if (error?.length) {
|
||||||
return (
|
return (
|
||||||
@ -108,62 +124,75 @@ function PaymentModal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["payment-modal"]}>
|
<>
|
||||||
<Title variant="h3" className={styles.title}>
|
{isLoading && (
|
||||||
Choose payment method
|
<div className={styles["payment-modal"]}>
|
||||||
</Title>
|
<div className={styles["payment-loader"]}>
|
||||||
<PaymentMethodsChoice
|
<Loader />
|
||||||
paymentMethods={paymentMethodsButtons}
|
</div>
|
||||||
selectedPaymentMethod={selectedPaymentMethod}
|
|
||||||
onSelectPaymentMethod={onSelectPaymentMethod}
|
|
||||||
/>
|
|
||||||
{_activeProduct && (
|
|
||||||
<div>
|
|
||||||
{!noTrial && (
|
|
||||||
<>
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
You will be charged only{" "}
|
|
||||||
<b>${getPrice(_activeProduct)} for your 3-day trial.</b>
|
|
||||||
</p>
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
We`ll <b>email you a reminder</b> before your trial period ends.
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<p className={styles["sub-plan-description"]}>
|
|
||||||
Cancel anytime. The charge will appear on your bill as witapps.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles["payment-method-container"]}>
|
<div
|
||||||
{stripePromise && clientSecret && (
|
className={`${styles["payment-modal"]} ${isLoading ? styles.hide : ""}`}
|
||||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
>
|
||||||
<CheckAvailableStripeButton
|
<Title variant="h3" className={styles.title}>
|
||||||
activeProduct={_activeProduct}
|
Choose payment method
|
||||||
clientSecret={clientSecret}
|
</Title>
|
||||||
/>
|
<PaymentMethodsChoice
|
||||||
{selectedPaymentMethod === EPaymentMethod.PAYMENT_BUTTONS && (
|
paymentMethods={paymentMethodsButtons}
|
||||||
<div className={styles["payment-method"]}>
|
selectedPaymentMethod={selectedPaymentMethod}
|
||||||
{paymentRequest && (
|
onSelectPaymentMethod={onSelectPaymentMethod}
|
||||||
<StripeButton paymentRequest={paymentRequest} />
|
/>
|
||||||
)}
|
{_activeProduct && (
|
||||||
</div>
|
<div>
|
||||||
|
{!noTrial && (
|
||||||
|
<>
|
||||||
|
<p className={styles["sub-plan-description"]}>
|
||||||
|
You will be charged only{" "}
|
||||||
|
<b>${getPrice(_activeProduct)} for your 3-day trial.</b>
|
||||||
|
</p>
|
||||||
|
<p className={styles["sub-plan-description"]}>
|
||||||
|
We`ll <b>email you a reminder</b> before your trial period
|
||||||
|
ends.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectedPaymentMethod === EPaymentMethod.CREDIT_CARD && (
|
<p className={styles["sub-plan-description"]}>
|
||||||
<CheckoutForm
|
Cancel anytime. The charge will appear on your bill as witapps.
|
||||||
confirmType={paymentType}
|
</p>
|
||||||
subscriptionReceiptId={paymentIntentId}
|
</div>
|
||||||
returnUrl={returnUrl}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Elements>
|
|
||||||
)}
|
)}
|
||||||
|
<div className={styles["payment-method-container"]}>
|
||||||
|
{stripePromise && clientSecret && (
|
||||||
|
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
||||||
|
<ExpressCheckoutStripe
|
||||||
|
clientSecret={clientSecret}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
isHide={
|
||||||
|
selectedPaymentMethod !== EPaymentMethod.PAYMENT_BUTTONS
|
||||||
|
}
|
||||||
|
onAvailable={(_isAvailable, _availableMethods) =>
|
||||||
|
onAvailableExpressCheckout(_isAvailable, _availableMethods)
|
||||||
|
}
|
||||||
|
onChangeLoading={(isLoading) =>
|
||||||
|
setIsLoadingExpressCheckout(isLoading)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{selectedPaymentMethod === EPaymentMethod.CREDIT_CARD && (
|
||||||
|
<CheckoutForm
|
||||||
|
confirmType={paymentType}
|
||||||
|
subscriptionReceiptId={paymentIntentId}
|
||||||
|
returnUrl={returnUrl}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Elements>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<SecurityPayments />
|
||||||
|
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
|
||||||
</div>
|
</div>
|
||||||
<SecurityPayments />
|
</>
|
||||||
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,12 @@
|
|||||||
color: #2f2e37;
|
color: #2f2e37;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.payment-modal.hide {
|
||||||
|
min-height: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|||||||
@ -4,26 +4,28 @@ import { TCanMakePaymentResult } from "@/components/PaymentPage/methods/StripeBu
|
|||||||
interface IPaymentButtonsProps {
|
interface IPaymentButtonsProps {
|
||||||
availableMethods: TCanMakePaymentResult;
|
availableMethods: TCanMakePaymentResult;
|
||||||
}
|
}
|
||||||
|
const Image = ({ availableMethods }: IPaymentButtonsProps) => {
|
||||||
|
if (!availableMethods) return <></>;
|
||||||
|
if (availableMethods["applePay"]) {
|
||||||
|
return <img src="/applepay.webp" alt="ApplePay" />;
|
||||||
|
}
|
||||||
|
if (availableMethods["googlePay"]) {
|
||||||
|
return <img src="/google-pay-mark.png" alt="google" />;
|
||||||
|
}
|
||||||
|
if (availableMethods["amazon"]) {
|
||||||
|
return <img src="/amazon-pay-mark.png" alt="AmazonPay" />;
|
||||||
|
}
|
||||||
|
if (availableMethods["link"]) {
|
||||||
|
return <img src="/link-pay-mark.png" alt="LinkPay" />;
|
||||||
|
}
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
function PaymentButtons({ availableMethods }: IPaymentButtonsProps) {
|
function PaymentButtons({ availableMethods }: IPaymentButtonsProps) {
|
||||||
if (!availableMethods) return <></>;
|
if (!availableMethods) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
{availableMethods["applePay"] && (
|
<Image availableMethods={availableMethods} />
|
||||||
<img src="/applepay.webp" alt="ApplePay" />
|
|
||||||
)}
|
|
||||||
{availableMethods["googlePay"] && (
|
|
||||||
<img
|
|
||||||
src="/google-pay-mark.png"
|
|
||||||
alt="google"
|
|
||||||
style={{
|
|
||||||
height: "36px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{availableMethods["link"] && (
|
|
||||||
<img src="/link-pay-mark.png" alt="LinkPay" />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user