From 1fc35e973da88adef950243197b3a135355880b5 Mon Sep 17 00:00:00 2001 From: gofnnp Date: Sun, 22 Oct 2023 04:16:48 +0400 Subject: [PATCH] feat: add success and fail payment pages, fix payment system --- public/ExclamationIcon.png | Bin 0 -> 3798 bytes public/SuccessIcon.png | Bin 0 -> 1718 bytes src/api/resources/UserSubscriptionReceipts.ts | 144 +++++++++++------- src/components/App/index.tsx | 16 ++ src/components/BreathPage/index.tsx | 6 +- src/components/CompatResultPage/index.tsx | 5 +- src/components/HomePage/index.tsx | 3 +- .../methods/Stripe/CheckoutForm.tsx | 11 +- .../PaymentPage/methods/Stripe/Modal.tsx | 35 ++--- .../PaymentPage/results/ErrorPage/index.tsx | 30 ++++ .../results/ErrorPage/styles.module.css | 38 +++++ .../PaymentPage/results/SuccessPage/index.tsx | 25 +++ .../results/SuccessPage/styles.module.css | 25 +++ src/components/PaymentPage/results/index.tsx | 21 +++ src/components/WallpaperPage/index.tsx | 3 +- src/routes.ts | 9 ++ 16 files changed, 279 insertions(+), 92 deletions(-) create mode 100644 public/ExclamationIcon.png create mode 100644 public/SuccessIcon.png create mode 100644 src/components/PaymentPage/results/ErrorPage/index.tsx create mode 100644 src/components/PaymentPage/results/ErrorPage/styles.module.css create mode 100644 src/components/PaymentPage/results/SuccessPage/index.tsx create mode 100644 src/components/PaymentPage/results/SuccessPage/styles.module.css create mode 100644 src/components/PaymentPage/results/index.tsx diff --git a/public/ExclamationIcon.png b/public/ExclamationIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..a098232a9231525f05e347e81b9d08096f9bd681 GIT binary patch literal 3798 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 M07*qoM6N<$f=Uf2`Tzg` literal 0 HcmV?d00001 diff --git a/public/SuccessIcon.png b/public/SuccessIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..2110b7ebab6afa476974211efa086ba9d791e774 GIT binary patch literal 1718 zcmV;n21)seP)p_i*|7yRu>>BCZ^3gA3cZ(u;nwW97CDCX(@~GLO$Q_) z4g2uvG1M&Ov76wnSYBj~O{jC*>HJx@$bn)59*d20U_iN6rmI@W{+!;1vZAGBbC7}gu?j2 zcaLX>wa9aXgB`#xph&=Ge1Gljjc3QT$a6eew&XLrNLVZW)NLQnpQ=Tkf@aw)dL*7| zKuyRrKA{8!xVZ0ho`pK=mJI3R6Cw|udk}TL@*?v>e6Yi?YyrU0GRr1XxfvgG6TA;~Km|6~dA@s+^y!tdaHcGq zNTs?9QDj(X%O+BKk;7m-vD8ya z5|&M*^dhTP0fj`Qlw>Hi$U0L>QZI)RgHZ*HS$U3TkR4ARuh*dy+j8@Dkoydq)K)(VKr4l(WmhIWUgA##K1;hqBRm&z)8j($> zlw>G{$aqyi6m77ZrxYUNRRKMq4R-SsKK+zcN=b&ox8$r+N;0eznfGv+}X8K&77p5LnW#bFiD?*A+Lb+FKq z*_^*0fOW|P?ZM)#sl{6i@B3b!@VG$s$zGin+OT_)oH9hT6RD_PGh**nWmJaD|kd)-`xg-SS+lk=z}T0 zd_T4f_~|^Qlw`123Sa{2Y<~TsseT!+041fw{JsgxCStM6Pr9}%3Z0JQu{$D(-OnK8t?5*Sf|kkERY>XUQNqGHR6!BeC0?1dY$8w7YT|u)%`YiH0mpGXS~gI=DjvKCtpT7oo8iO{KGI$r(F9rL&b6AtqMqm$n;ZKnNA3v@0E;kV8thxW!uLrQb|i> zX5?`o;KnfMlLe{Q#LikMQ8LAp%q`{DT|#)6mW+mEdV*$yq6s-xg3rQP-qkVB;RyWoz4 z+RbbB^*EpmcN{eFttD2GW?{K0q-)_cI1Xij(=IGGMXG{BY{#KW-YlC)>Z(p`$B`CO zRX{2z*C!)84mol>*v+F{pNt&ikRwO&iB+H!f#b$F5_6MBPaFk`$Qm3+EEo&RO@X$Y z!KCBJLrO^o)HNeU97j%4N;04?%t6np2#B|rC<5A+nBm4arWC}oiD+A5rp0j-#IlKK zT`c+SVBj!+tZLTtXw zc%ep)7i?2%9evu}`5j6^W+KnvWm~PawI7*<_(false); const [leoApng, setLeoApng] = useState(Error); const navigate = useNavigate(); const api = useApi(); + const dispatch = useDispatch(); const closeSpecialOfferAttention = () => { setIsSpecialOfferOpen(false); @@ -66,6 +70,15 @@ function App(): JSX.Element { const { data } = useApiCall(assetsData); + useEffect(() => { + // TODO: remove later + dispatch( + actions.token.update( + "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjQwNjEyLCJpYXQiOjE2OTc5MjY0MTksImV4cCI6MTcwNjU2NjQxOSwianRpIjoiZTg0NWE0ZmUtYmVmNy00ODNmLWIwMzgtYjlkYzBlZjk1MjNmIiwiZW1haWwiOiJvdGhlcjJAZXhhbXBsZS5jb20iLCJzdGF0ZSI6InByb3ZlbiIsImxvYyI6ImVuIiwidHoiOjAsInR5cGUiOiJlbWFpbCIsImlzcyI6ImNvbS5saWZlLmF1cmEifQ.ijaHDiNRLUIKdkziVB-zt8DA8WNH7RNwvYkp2EGDxTM" + ) + ); + }, [dispatch]); + useEffect(() => { async function getApng() { if (!data) return; @@ -125,6 +138,9 @@ function App(): JSX.Element { element={} /> } /> + } /> + } /> + } /> } diff --git a/src/components/BreathPage/index.tsx b/src/components/BreathPage/index.tsx index e530a8a..ca23057 100644 --- a/src/components/BreathPage/index.tsx +++ b/src/components/BreathPage/index.tsx @@ -67,8 +67,8 @@ function BreathPage({ leoApng }: BreathPageProps): JSX.Element { setIsOpenModal(false); }; - const token = - "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw"; + + const token = useSelector(selectors.selectToken) const createCallback = useCallback(async () => { const data: UserCallbacks.PayloadPost = { data: { @@ -100,7 +100,7 @@ function BreathPage({ leoApng }: BreathPageProps): JSX.Element { } return createCallbackRequest.user_callback; - }, [api, dispatch]); + }, [api, dispatch, token]); useApiCall(createCallback); diff --git a/src/components/CompatResultPage/index.tsx b/src/components/CompatResultPage/index.tsx index 92a1249..16a737a 100644 --- a/src/components/CompatResultPage/index.tsx +++ b/src/components/CompatResultPage/index.tsx @@ -12,8 +12,7 @@ import FullScreenModal from "../FullScreenModal"; import CompatibilityLoading from "../CompatibilityLoading"; function CompatResultPage(): JSX.Element { - const token = - "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw"; + const token = useSelector(selectors.selectToken) const { t } = useTranslation(); const navigate = useNavigate(); const api = useApi(); @@ -82,7 +81,7 @@ function CompatResultPage(): JSX.Element { setText(aICompat?.compat?.body || "Loading..."); return aICompat.compat; - }, [api, rightUser, categoryId, birthdate]); + }, [api, rightUser, categoryId, birthdate, token]); useApiCall(loadData); diff --git a/src/components/HomePage/index.tsx b/src/components/HomePage/index.tsx index 6faf788..ea935ab 100644 --- a/src/components/HomePage/index.tsx +++ b/src/components/HomePage/index.tsx @@ -34,8 +34,7 @@ const buttonTextFormatter = (text: string): JSX.Element => { }; function HomePage(): JSX.Element { - const token = - "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw"; + const token = useSelector(selectors.selectToken) const { t } = useTranslation(); const navigate = useNavigate(); const dispatch = useDispatch(); diff --git a/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx b/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx index c9daef3..2487d31 100644 --- a/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx +++ b/src/components/PaymentPage/methods/Stripe/CheckoutForm.tsx @@ -23,20 +23,15 @@ export default function CheckoutForm() { setIsProcessing(true); - const { error, paymentIntent } = await stripe.confirmPayment({ + const { error } = await stripe.confirmPayment({ elements, confirmParams: { - return_url: window.location.href, - }, - redirect: "if_required", + return_url: `https://${window.location.host}/payment/result`, + } }); if (error) { setMessage(error?.message || "Oops! Something went wrong."); - } else if (paymentIntent && paymentIntent.status === "succeeded") { - setMessage("Payment succeeded!"); - } else { - setMessage("Unexpected state"); } setIsProcessing(false); diff --git a/src/components/PaymentPage/methods/Stripe/Modal.tsx b/src/components/PaymentPage/methods/Stripe/Modal.tsx index 6e19d6f..daa0eea 100644 --- a/src/components/PaymentPage/methods/Stripe/Modal.tsx +++ b/src/components/PaymentPage/methods/Stripe/Modal.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from "react"; import { Stripe, loadStripe } from "@stripe/stripe-js"; import { Elements } from "@stripe/react-stripe-js"; import CheckoutForm from "./CheckoutForm"; +import { useAuth } from "@/auth"; interface StripeModalProps { open: boolean; @@ -16,14 +17,15 @@ interface StripeModalProps { export function StripeModal({ open, onClose, -// onSuccess, +}: // onSuccess, // onError, -}: StripeModalProps): JSX.Element { +StripeModalProps): JSX.Element { const api = useApi(); + const { token } = useAuth(); const [stripePromise, setStripePromise] = useState | null>(null); const [clientSecret, setClientSecret] = useState(""); - const isLoading = false; + const [isLoading, setIsLoading ] = useState(true); useEffect(() => { (async () => { @@ -33,25 +35,18 @@ export function StripeModal({ }, [api]); useEffect(() => { - fetch("https://aura.wit.life/api/v1/user/subscription_receipts.json", { - method: "POST", - headers: { - Authorization: - "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw", - "Content-Type": "application/json", - }, - body: JSON.stringify({ - way: "stripe", - subscription_receipt: { - item_interval: "year", - }, - }), - }).then(async (res) => { - const { subscription_receipt } = await res.json(); + if (!open) return; + (async () => { + + const { subscription_receipt } = await api.createSubscriptionReceipt({ + token, + itemInterval: "year", + }); const { client_secret } = subscription_receipt.data; setClientSecret(client_secret); - }); - }, []); + setIsLoading(false); + })(); + }, [api, token, open]); const handleClose = () => { onClose(); diff --git a/src/components/PaymentPage/results/ErrorPage/index.tsx b/src/components/PaymentPage/results/ErrorPage/index.tsx new file mode 100644 index 0000000..b5eab29 --- /dev/null +++ b/src/components/PaymentPage/results/ErrorPage/index.tsx @@ -0,0 +1,30 @@ +import { useNavigate } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import routes from "@/routes"; +import styles from "./styles.module.css"; +import Title from "@/components/Title"; +import MainButton from "@/components/MainButton"; + +function PaymentFailPage(): JSX.Element { + const { t } = useTranslation(); + const navigate = useNavigate(); + const handleNext = () => navigate(routes.client.paymentMethod()); + + return ( +
+ Exclamation Icon +
+ {t("auweb.pay_bad.title")} +

{t("auweb.pay_bad.text1")}

+
+
+

{t("auweb.pay_bad.text2")}

+ + {t("auweb.pay_bad.button")} + +
+
+ ); +} + +export default PaymentFailPage; diff --git a/src/components/PaymentPage/results/ErrorPage/styles.module.css b/src/components/PaymentPage/results/ErrorPage/styles.module.css new file mode 100644 index 0000000..fa479f4 --- /dev/null +++ b/src/components/PaymentPage/results/ErrorPage/styles.module.css @@ -0,0 +1,38 @@ +.page { + position: relative; + height: calc(100vh - 50px); + /* max-height: -webkit-fill-available; */ + overflow-y: scroll; + justify-content: center; + gap: 80px; +} + +.text { + display: flex; + flex-direction: column; +} + +.list { + font-weight: 500; + white-space: pre-wrap; + text-align: left; +} + +.description { + font-weight: 500; + text-align: center; +} + +.button { + width: 100%; + max-width: 260px; + border-radius: 50px; + background-color: #fe2b57; +} + +.bottom { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; +} diff --git a/src/components/PaymentPage/results/SuccessPage/index.tsx b/src/components/PaymentPage/results/SuccessPage/index.tsx new file mode 100644 index 0000000..ba9aed4 --- /dev/null +++ b/src/components/PaymentPage/results/SuccessPage/index.tsx @@ -0,0 +1,25 @@ +import { useNavigate } from 'react-router-dom' +import { useTranslation } from "react-i18next"; +import routes from '@/routes' +import styles from "./styles.module.css"; +import Title from "@/components/Title"; +import MainButton from "@/components/MainButton"; + +function PaymentSuccessPage(): JSX.Element { + const { t } = useTranslation(); + const navigate = useNavigate() + const handleNext = () => navigate(routes.client.home()) + + return ( +
+ Success Icon +
+ {t("auweb.pay_good.title")} +

{t("auweb.pay_good.text1")}

+
+ {t("auweb.pay_good.button")} +
+ ); +} + +export default PaymentSuccessPage; diff --git a/src/components/PaymentPage/results/SuccessPage/styles.module.css b/src/components/PaymentPage/results/SuccessPage/styles.module.css new file mode 100644 index 0000000..0c0efb9 --- /dev/null +++ b/src/components/PaymentPage/results/SuccessPage/styles.module.css @@ -0,0 +1,25 @@ +.page { + position: relative; + flex: auto; + height: calc(100vh - 50px); + max-height: -webkit-fill-available; + justify-content: center; + gap: 80px; +} + +.text { + display: flex; + flex-direction: column; +} + +.text > p { + text-align: center; + font-weight: 500; +} + +.button { + width: 100%; + max-width: 260px; + border-radius: 50px; + background-color: #FE2B57; +} \ No newline at end of file diff --git a/src/components/PaymentPage/results/index.tsx b/src/components/PaymentPage/results/index.tsx new file mode 100644 index 0000000..e9356e8 --- /dev/null +++ b/src/components/PaymentPage/results/index.tsx @@ -0,0 +1,21 @@ +import { useNavigate } from "react-router-dom"; +import routes from "@/routes"; +import { useEffect } from "react"; +import { useSearchParams } from "react-router-dom"; + +function PaymentResultPage(): JSX.Element { + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const status = searchParams.get("redirect_status"); + + useEffect(() => { + if (status === "succeeded") { + return navigate(routes.client.paymentSuccess()); + } + return navigate(routes.client.paymentFail()); + }, [navigate, status]); + + return <>; +} + +export default PaymentResultPage; diff --git a/src/components/WallpaperPage/index.tsx b/src/components/WallpaperPage/index.tsx index e917a13..3719670 100644 --- a/src/components/WallpaperPage/index.tsx +++ b/src/components/WallpaperPage/index.tsx @@ -58,8 +58,7 @@ function WallpaperPage(): JSX.Element { const api = useApi(); const { i18n } = useTranslation(); const locale = i18n.language; - const token = - "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw"; + const token = useSelector(selectors.selectToken) const { user, diff --git a/src/routes.ts b/src/routes.ts index 6c47850..fd689fa 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -17,6 +17,9 @@ const routes = { attention: () => [host, "attention"].join("/"), feedback: () => [host, "feedback"].join("/"), paymentMethod: () => [host, "payment", "method"].join("/"), + paymentResult: () => [host, "payment", "result"].join("/"), + paymentSuccess: () => [host, "payment", "success"].join("/"), + paymentFail: () => [host, "payment", "fail"].join("/"), wallpaper: () => [host, "wallpaper"].join("/"), static: () => [host, "static", ":typeId"].join("/"), legal: (type: string) => [host, "static", type].join("/"), @@ -115,6 +118,9 @@ export const withoutFooterRoutes = [ routes.client.compatibilityResult(), routes.client.home(), routes.client.breathResult(), + routes.client.paymentResult(), + routes.client.paymentSuccess(), + routes.client.paymentFail(), ]; export const hasNoFooter = (path: string) => !withoutFooterRoutes.includes(path); @@ -134,6 +140,9 @@ export const withoutHeaderRoutes = [ routes.client.compatibility(), routes.client.subscription(), routes.client.paymentMethod(), + routes.client.paymentResult(), + routes.client.paymentSuccess(), + routes.client.paymentFail(), ]; export const hasNoHeader = (path: string) => !withoutHeaderRoutes.includes(path);