AW-22-deleteChargebee
@ -89,7 +89,6 @@
|
||||
<img src="/leo.png" alt="Aura - Energy of your Horoscope" />
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://js.chargebee.com/v2/chargebee.js"></script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
29
package-lock.json
generated
@ -8,7 +8,6 @@
|
||||
"name": "aurawebapp",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@chargebee/chargebee-js-react-wrapper": "^0.6.3",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@smakss/react-scroll-direction": "^4.0.4",
|
||||
"@stripe/react-stripe-js": "^2.3.1",
|
||||
@ -30,7 +29,6 @@
|
||||
"unique-names-generator": "^4.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chargebee/chargebee-js-types": "^1.0.1",
|
||||
"@types/node": "^20.5.1",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
@ -417,21 +415,6 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@chargebee/chargebee-js-react-wrapper": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@chargebee/chargebee-js-react-wrapper/-/chargebee-js-react-wrapper-0.6.3.tgz",
|
||||
"integrity": "sha512-U3KJLZZiUxxkW4HAkAZr2bs6r4HqL1S59zo3AAp4UYtJZbxmBpfX5e/MlsSENvsRxd2GvOpumcHr8rR4V0D5vw==",
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^17.0.0",
|
||||
"react-dom": "^18.0.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@chargebee/chargebee-js-types": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@chargebee/chargebee-js-types/-/chargebee-js-types-1.0.1.tgz",
|
||||
"integrity": "sha512-JsHlIAjZDwX2Q/vDGN4xzKRC8n1K4xCwzKl7wZOOwUH9ow030CRspVRkP3OWHrY5gLmpbmICc/iK2aptF3t/Ow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
@ -3865,18 +3848,6 @@
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@chargebee/chargebee-js-react-wrapper": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@chargebee/chargebee-js-react-wrapper/-/chargebee-js-react-wrapper-0.6.3.tgz",
|
||||
"integrity": "sha512-U3KJLZZiUxxkW4HAkAZr2bs6r4HqL1S59zo3AAp4UYtJZbxmBpfX5e/MlsSENvsRxd2GvOpumcHr8rR4V0D5vw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@chargebee/chargebee-js-types": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@chargebee/chargebee-js-types/-/chargebee-js-types-1.0.1.tgz",
|
||||
"integrity": "sha512-JsHlIAjZDwX2Q/vDGN4xzKRC8n1K4xCwzKl7wZOOwUH9ow030CRspVRkP3OWHrY5gLmpbmICc/iK2aptF3t/Ow==",
|
||||
"dev": true
|
||||
},
|
||||
"@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chargebee/chargebee-js-react-wrapper": "^0.6.3",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@smakss/react-scroll-direction": "^4.0.4",
|
||||
"@stripe/react-stripe-js": "^2.3.1",
|
||||
@ -32,7 +31,6 @@
|
||||
"unique-names-generator": "^4.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chargebee/chargebee-js-types": "^1.0.1",
|
||||
"@types/node": "^20.5.1",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
|
||||
@ -13,7 +13,6 @@ import {
|
||||
SubscriptionCheckout,
|
||||
SubscriptionReceipts,
|
||||
SubscriptionStatus,
|
||||
PaymentIntents,
|
||||
AICompatCategories,
|
||||
AICompats,
|
||||
AIRequests,
|
||||
@ -50,7 +49,6 @@ const api = {
|
||||
getSubscriptionStatus: createMethod<SubscriptionStatus.Payload, SubscriptionStatus.Response>(SubscriptionStatus.createRequest),
|
||||
getSubscriptionReceipt: createMethod<SubscriptionReceipts.GetPayload, SubscriptionReceipts.Response>(SubscriptionReceipts.createGetRequest),
|
||||
createSubscriptionReceipt: createMethod<SubscriptionReceipts.Payload, SubscriptionReceipts.Response>(SubscriptionReceipts.createRequest),
|
||||
createPaymentIntent: createMethod<PaymentIntents.Payload, PaymentIntents.Response>(PaymentIntents.createRequest),
|
||||
getAiCompatCategories: createMethod<AICompatCategories.Payload, AICompatCategories.Response>(AICompatCategories.createRequest),
|
||||
getAiCompat: createMethod<AICompats.Payload, AICompats.Response>(AICompats.createRequest),
|
||||
getAiRequest: createMethod<AIRequests.Payload, AIRequests.Response>(AIRequests.createRequest),
|
||||
|
||||
@ -13,7 +13,6 @@ export interface Response {
|
||||
active_iaps: ActiveIAps[]
|
||||
version: string
|
||||
apple_music_api: AppleMusicApi
|
||||
chargebee: ChargebeeConfig
|
||||
first_open_subscription_popup: boolean
|
||||
runs_before_subscription_popup: number
|
||||
appirater_alerts: AppiraterAlertAppiraterAlert[]
|
||||
@ -53,12 +52,6 @@ export interface AppleMusicApi {
|
||||
jwt: string
|
||||
}
|
||||
|
||||
export interface ChargebeeConfig {
|
||||
site: string
|
||||
publishableKey: string
|
||||
gatewayAccountId: string
|
||||
}
|
||||
|
||||
export const createRequest = ({ bundleId }: Payload): Request => {
|
||||
const url = new URL(routes.server.apps(bundleId))
|
||||
return new Request(url, { method: 'GET', headers: getBaseHeaders() })
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
import { PaymentIntent } from '@chargebee/chargebee-js-types'
|
||||
import { AuthPayload } from '../types'
|
||||
import { getAuthHeaders } from '../utils'
|
||||
import routes from '@/routes'
|
||||
|
||||
export interface Payload extends AuthPayload {
|
||||
paymentMethod: PaymentMethod
|
||||
currencyCode: CurrencyCode
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
payment_intent: PaymentIntent
|
||||
customer: Customer
|
||||
}
|
||||
|
||||
export type PaymentMethod = 'apple_pay' | 'google_pay' | 'card'
|
||||
export type CurrencyCode = 'USD'
|
||||
|
||||
export interface Customer {
|
||||
id: string
|
||||
email: string
|
||||
auto_collection: 'on' | 'off'
|
||||
net_term_days: number
|
||||
allow_direct_debit: boolean
|
||||
taxability: 'taxable' | 'exempt'
|
||||
created_at: number
|
||||
updated_at: number
|
||||
pii_cleared: 'active' | 'scheduled_for_clear' | 'cleared'
|
||||
channel: 'web' | 'app_store' | 'play_store'
|
||||
resource_version: number
|
||||
deleted: boolean
|
||||
card_status: 'no_card' | 'valid' | 'expiring' | 'expired'
|
||||
promotional_credits: number
|
||||
refundable_credits: number
|
||||
excess_payments: number
|
||||
unbilled_charges: number
|
||||
preferred_currency_code: CurrencyCode
|
||||
}
|
||||
|
||||
export const createRequest = ({ token, paymentMethod, currencyCode }: Payload): Request => {
|
||||
const url = new URL(routes.server.paymentIntents())
|
||||
const body = JSON.stringify({
|
||||
payment_intent: {
|
||||
payment_method_type: paymentMethod,
|
||||
currency_code: currencyCode,
|
||||
}
|
||||
})
|
||||
return new Request(url, { method: 'POST', headers: getAuthHeaders(token), body })
|
||||
}
|
||||
@ -6,12 +6,6 @@ export interface GetPayload extends AuthPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ChargebeeReceiptPayload extends AuthPayload {
|
||||
itemPriceId: string;
|
||||
gwToken: string;
|
||||
referenceId?: string;
|
||||
}
|
||||
|
||||
export interface AppleReceiptPayload extends AuthPayload {
|
||||
receiptData: string;
|
||||
autorenewable?: boolean;
|
||||
@ -33,7 +27,6 @@ export interface PayPalReceiptPayload extends AuthPayload {
|
||||
}
|
||||
|
||||
export type Payload =
|
||||
| ChargebeeReceiptPayload
|
||||
| AppleReceiptPayload
|
||||
| StripeReceiptPayload
|
||||
| PayPalReceiptPayload;
|
||||
@ -78,12 +71,6 @@ interface IPayPalLink {
|
||||
method: "GET" | "PATCH";
|
||||
}
|
||||
|
||||
function createRequest({
|
||||
token,
|
||||
itemPriceId,
|
||||
gwToken,
|
||||
referenceId,
|
||||
}: ChargebeeReceiptPayload): Request;
|
||||
function createRequest({
|
||||
token,
|
||||
receiptData,
|
||||
@ -104,16 +91,6 @@ function createRequest(payload: Payload): Request {
|
||||
}
|
||||
|
||||
function getDataPayload(payload: Payload) {
|
||||
if ("itemPriceId" in payload && "gwToken" in payload) {
|
||||
return {
|
||||
way: "chargebee",
|
||||
subscription_receipt: {
|
||||
item_price_id: payload.itemPriceId,
|
||||
gw_token: payload.gwToken,
|
||||
reference_id: payload.referenceId,
|
||||
},
|
||||
};
|
||||
}
|
||||
if ("receiptData" in payload) {
|
||||
return {
|
||||
way: "apple",
|
||||
|
||||
@ -11,7 +11,6 @@ export * as SubscriptionItems from "./UserSubscriptionItemPrices";
|
||||
export * as SubscriptionCheckout from "./UserSubscriptionCheckout";
|
||||
export * as SubscriptionStatus from "./UserSubscriptionStatus";
|
||||
export * as SubscriptionReceipts from "./UserSubscriptionReceipts";
|
||||
export * as PaymentIntents from "./UserPaymentIntents";
|
||||
export * as AICompatCategories from "./AICompatCategories";
|
||||
export * as AICompats from "./AICompats";
|
||||
export * as AIRequests from "./AIRequests";
|
||||
|
||||
@ -1,74 +1,15 @@
|
||||
import { usePayment } from "@/payment";
|
||||
import routes from "@/routes";
|
||||
import { selectors } from "@/store";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Header from "../Header";
|
||||
import Loader from "../Loader";
|
||||
import Title from "../Title";
|
||||
import UserHeader from "../UserHeader";
|
||||
import ErrorModal from "./ErrorModal";
|
||||
import { ApplePayBanner, GooglePayBanner } from "./methods";
|
||||
import { StripeButton } from "./methods/Stripe";
|
||||
import secure from "./secure.png";
|
||||
import "./styles.css";
|
||||
// import { PayPalButton } from "./methods/PayPal/Button";
|
||||
// import { useAuth } from "@/auth";
|
||||
// import { useApi } from "@/api";
|
||||
// import { PayPalReceiptPayload } from "@/api/resources/UserSubscriptionReceipts";
|
||||
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
||||
|
||||
const getPrice = (activeSubPlan: ISubscriptionPlan | null) => {
|
||||
if (!activeSubPlan) return 0;
|
||||
return String(
|
||||
activeSubPlan?.trial?.price_cents
|
||||
? activeSubPlan.trial.price_cents / 100
|
||||
: 0
|
||||
);
|
||||
};
|
||||
|
||||
function PaymentPage(): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { applePay } = usePayment();
|
||||
// const api = useApi();
|
||||
// const { token } = useAuth();
|
||||
const [openErrorModal, setOpenErrorModal] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const isLoading = applePay === null;
|
||||
const isApplePayAvailable =
|
||||
import.meta.env.PROD && applePay?.canMakePayments();
|
||||
const email = useSelector(selectors.selectEmail);
|
||||
const activeSubPlan = useSelector(selectors.selectActiveSubPlan);
|
||||
|
||||
// Do not allow to go to this page if there is no other payment methods
|
||||
useEffect(() => {
|
||||
// Have only Stripe for now
|
||||
navigate(routes.client.paymentStripe());
|
||||
}, []);
|
||||
|
||||
const navigateToStripe = () => {
|
||||
navigate(routes.client.paymentStripe());
|
||||
};
|
||||
|
||||
// const navigateToPayPal = async () => {
|
||||
// const { subscription_receipt } = await api.createSubscriptionReceipt({
|
||||
// token,
|
||||
// itemInterval: "year",
|
||||
// way: "paypal",
|
||||
// subscription_receipt: {
|
||||
// sub_plan_id: activeSubPlan?.id || "",
|
||||
// },
|
||||
// } as PayPalReceiptPayload);
|
||||
// const url = subscription_receipt.data.links?.find(
|
||||
// (link) => link.rel === "approve"
|
||||
// )?.href;
|
||||
// if (!url?.length) {
|
||||
// return setOpenErrorModal(true);
|
||||
// }
|
||||
// window.location.href = url;
|
||||
// };
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -78,38 +19,7 @@ function PaymentPage(): JSX.Element {
|
||||
/>
|
||||
<UserHeader email={email} />
|
||||
<section className="page">
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<>
|
||||
<div className="page-header">
|
||||
{isApplePayAvailable ? <ApplePayBanner /> : <GooglePayBanner />}
|
||||
<img src={secure} alt="100% Secure" />
|
||||
</div>
|
||||
<Title variant="h1" className="mb-45">
|
||||
{t("choose_payment")}
|
||||
</Title>
|
||||
<div className="payment-buttons-container">
|
||||
{/* <PayPalButton onClick={navigateToPayPal} /> */}
|
||||
<StripeButton onClick={navigateToStripe} />
|
||||
</div>
|
||||
<p className="payment-warining">
|
||||
{t("will_be_charged", {
|
||||
strongText: (
|
||||
<strong>
|
||||
{t("trial_price", {
|
||||
price: getPrice(activeSubPlan || null),
|
||||
})}
|
||||
</strong>
|
||||
),
|
||||
})}
|
||||
</p>
|
||||
<ErrorModal
|
||||
open={openErrorModal}
|
||||
onClose={() => setOpenErrorModal(false)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Loader />
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
|
||||
|
Before Width: | Height: | Size: 74 KiB |
@ -1,5 +0,0 @@
|
||||
import applePaySafeCheckout from './Apple-Pay.png'
|
||||
|
||||
export function ApplePayBanner (): JSX.Element {
|
||||
return <img src={applePaySafeCheckout} alt='Guaranteed safe checkout' />
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PaymentIntent } from '@chargebee/chargebee-js-types'
|
||||
import { useApi, useApiCall, extractErrorMessage, SubscriptionReceipts } from '@/api'
|
||||
import { usePayment, ApplePayButtonOptions } from '@/payment'
|
||||
import { useAuth } from '@/auth'
|
||||
import Loader, { LoaderColor } from '@/components/Loader'
|
||||
import ErrorText from '@/components/ErrorText'
|
||||
|
||||
const currencyCode = 'USD'
|
||||
const paymentMethod = 'apple_pay'
|
||||
const buttonId = 'apple-pay-btn'
|
||||
|
||||
interface ApplePayButtonProps {
|
||||
onSuccess: (receipt: SubscriptionReceipts.SubscriptionReceipt) => void
|
||||
onError: (error: Error) => void
|
||||
}
|
||||
|
||||
export function ApplePayButton({ onSuccess, onError }: ApplePayButtonProps): JSX.Element {
|
||||
const api = useApi()
|
||||
const { i18n } = useTranslation()
|
||||
const { token } = useAuth()
|
||||
const { applePay } = usePayment()
|
||||
const [isMounting, setIsMounting] = useState<boolean>(true)
|
||||
const loadData = useCallback(() => {
|
||||
return api.createPaymentIntent({ token, paymentMethod, currencyCode })
|
||||
.then(({ payment_intent }) => payment_intent)
|
||||
}, [api, token])
|
||||
const { data, error, isPending } = useApiCall<PaymentIntent>(loadData)
|
||||
|
||||
if (error) console.error(error)
|
||||
|
||||
useEffect(() => {
|
||||
if (data === null) return
|
||||
const buttonOptions: ApplePayButtonOptions = {
|
||||
buttonColor: 'black',
|
||||
buttonType: 'plain',
|
||||
locale: i18n.language
|
||||
}
|
||||
applePay?.setPaymentIntent(data)
|
||||
applePay?.mountPaymentButton(`#${buttonId}`, buttonOptions)
|
||||
.then(() => setIsMounting(false))
|
||||
.then(() => applePay?.handlePayment())
|
||||
.then((paymentIntent) => {
|
||||
return api.createSubscriptionReceipt({
|
||||
token, receiptData: paymentIntent.id, autorenewable: true, sandbox: true,
|
||||
})
|
||||
})
|
||||
.then(({ subscription_receipt }: SubscriptionReceipts.Response) => onSuccess(subscription_receipt))
|
||||
.catch((error: Error) => onError(error))
|
||||
}, [data, applePay, i18n.language, api, token, onSuccess, onError])
|
||||
|
||||
return (
|
||||
<div id={buttonId} className='pay-btn'>
|
||||
{isPending || isMounting ? <FakeApplePayButton /> : null}
|
||||
{error ? <ErrorText message={extractErrorMessage(error)} isShown={true} size='large'/> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FakeApplePayButton() {
|
||||
return (
|
||||
<div className='apple-pay-button-placeholder'>
|
||||
<Loader color={LoaderColor.White} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
export * from './Banner'
|
||||
export * from './Button'
|
||||
@ -1,18 +0,0 @@
|
||||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import MainButton from '@/components/MainButton'
|
||||
import card from './card.svg'
|
||||
|
||||
interface CardButtonProps {
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
export function CardButton({ onClick }: CardButtonProps): JSX.Element {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<MainButton color='blue' onClick={onClick}>
|
||||
<img className='payment-card' src={card} alt='Credit / Debit Card' />
|
||||
{t('card')}
|
||||
</MainButton>
|
||||
)
|
||||
}
|
||||
@ -1,146 +0,0 @@
|
||||
import { useCallback, useEffect, useRef, useState, ChangeEvent } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
CardCVV, CardComponent, CardExpiry, CardNumber, Provider
|
||||
} from '@chargebee/chargebee-js-react-wrapper'
|
||||
import ChargebeeComponents from '@chargebee/chargebee-js-react-wrapper/dist/components/ComponentGroup'
|
||||
import { PaymentIntent } from '@chargebee/chargebee-js-types'
|
||||
import { usePayment } from '@/payment'
|
||||
import { useApi, SubscriptionReceipts, useApiCall } from '@/api'
|
||||
import { useAuth } from '@/auth'
|
||||
import Modal from '@/components/Modal'
|
||||
import Title from '@/components/Title'
|
||||
import MainButton from '@/components/MainButton'
|
||||
import Loader from '@/components/Loader'
|
||||
import visa from './visa.svg'
|
||||
import mastercard from './mastercard.svg'
|
||||
import amex from './amex.svg'
|
||||
import diners from './diners.svg'
|
||||
import discover from './discover.svg'
|
||||
import { cardStyles } from './styles'
|
||||
|
||||
interface CardModalProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
onSuccess: (receipt: SubscriptionReceipts.SubscriptionReceipt) => void
|
||||
onError: (error: Error) => void
|
||||
}
|
||||
|
||||
interface Field {
|
||||
cardType: string | undefined
|
||||
complete: boolean
|
||||
empty: boolean
|
||||
error: Error | undefined
|
||||
field: 'number' | 'expiry' | 'cvv'
|
||||
key: string | undefined
|
||||
type: string
|
||||
}
|
||||
|
||||
type Status = 'idle' | 'loading' | 'filling' | 'subscribing' | 'ready' | 'success' | 'error'
|
||||
|
||||
const initCompletedFields = {
|
||||
number: false,
|
||||
expiry: false,
|
||||
cvv: false,
|
||||
}
|
||||
|
||||
type CompletedFields = typeof initCompletedFields
|
||||
|
||||
const isReady = (fields: CompletedFields) => Object.values(fields).every((complete: boolean) => complete)
|
||||
|
||||
const currencyCode = 'USD'
|
||||
const paymentMethod = 'card'
|
||||
const itemPriceId = 'aura-membership-2-week-USD'
|
||||
|
||||
export function CardModal({ open, onClose, onSuccess, onError }: CardModalProps): JSX.Element {
|
||||
const api = useApi()
|
||||
const cardRef = useRef<ChargebeeComponents>(null)
|
||||
const [status, setStatus] = useState<Status>('idle')
|
||||
const [fields, setFields] = useState(initCompletedFields)
|
||||
const { token, user } = useAuth()
|
||||
const { t, i18n } = useTranslation()
|
||||
const locale = i18n.language
|
||||
const isInit = status === 'idle'
|
||||
const isLoading = status === 'loading'
|
||||
const { chargebee } = usePayment()
|
||||
const loadData = useCallback(() => {
|
||||
return api.createPaymentIntent({ token, paymentMethod, currencyCode })
|
||||
.then(({ payment_intent }) => payment_intent)
|
||||
}, [api, token])
|
||||
const { data, error } = useApiCall<PaymentIntent>(loadData)
|
||||
const handleReady = () => setStatus('filling')
|
||||
const handleClose = () => {
|
||||
setStatus('loading')
|
||||
onClose()
|
||||
}
|
||||
const handleChange = ({ field, complete, error }: ChangeEvent & Field) => {
|
||||
setFields((state) => ({ ...state, [field]: complete && !error }))
|
||||
}
|
||||
const payWithCard = () => {
|
||||
if (data === null) return
|
||||
setStatus('subscribing')
|
||||
cardRef.current?.authorizeWith3ds(data, { email: user?.email }, {})
|
||||
.then((paymentIntent: PaymentIntent) => {
|
||||
return api.createSubscriptionReceipt({ token, itemPriceId, gwToken: paymentIntent.id })
|
||||
})
|
||||
.then(({ subscription_receipt }: SubscriptionReceipts.Response) => {
|
||||
setStatus('success')
|
||||
onSuccess(subscription_receipt)
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
setStatus('error')
|
||||
onError(error)
|
||||
})
|
||||
}
|
||||
|
||||
if (error) console.error(error)
|
||||
|
||||
useEffect(() => {
|
||||
if (status !== 'filling' && status !== 'ready' && status !== 'error') return
|
||||
setStatus(isReady(fields) ? 'ready' : 'filling')
|
||||
}, [fields, status])
|
||||
|
||||
useEffect(() => {
|
||||
if (isInit) setStatus('loading')
|
||||
}, [isInit])
|
||||
|
||||
return (
|
||||
<Modal open={open} onClose={handleClose}>
|
||||
{ isLoading ? <div className='payment-loader'><Loader /></div> : null}
|
||||
<div style={{ display: isLoading ? 'none' : 'block' }}>
|
||||
<div className='payment-modal-header'>
|
||||
<Title variant='h3' className='mb-0'>{t('card')}</Title>
|
||||
<div className='payment-card-list'>
|
||||
<img src={visa} alt='Visa Card' />
|
||||
<img src={mastercard} alt='Mastercard Card' />
|
||||
<img src={amex} alt='Amex Card' />
|
||||
<img src={diners} alt='Diners Card' />
|
||||
<img src={discover} alt='Discover Card' />
|
||||
</div>
|
||||
</div>
|
||||
<Provider cbInstance={chargebee}>
|
||||
<CardComponent ref={cardRef} locale={locale} styles={cardStyles} onReady={handleReady}>
|
||||
<div className="payment-input"><CardNumber onChange={handleChange} /></div>
|
||||
<div className='payment-group'>
|
||||
<div className="payment-input"><CardExpiry onChange={handleChange} /></div>
|
||||
<div className="payment-input"><CardCVV onChange={handleChange} /></div>
|
||||
</div>
|
||||
</CardComponent>
|
||||
</Provider>
|
||||
<p className='payment-inforamtion'>{t('charged_only')}</p>
|
||||
<MainButton color='blue' onClick={payWithCard} disabled={status !== 'ready'}>
|
||||
{ status === 'subscribing' ? <Loader /> : <><LockIcon />{t('start_trial')}</> }
|
||||
</MainButton>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
function LockIcon(): JSX.Element {
|
||||
return (
|
||||
<svg width="13" height="16" viewBox="0 0 13 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.5556 6.24219H1.44444C0.6467 6.24219 0 6.97481 0 7.87855V13.6058C0 14.5096 0.6467 15.2422 1.44444 15.2422H11.5556C12.3533 15.2422 13 14.5096 13 13.6058V7.87855C13 6.97481 12.3533 6.24219 11.5556 6.24219Z"></path>
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M6.5 0.242188C4.29086 0.242188 2.5 2.03305 2.5 4.24219V8.24219H10.5V4.24219C10.5 2.03305 8.70914 0.242188 6.5 0.242188ZM6.5 1.24219C4.84315 1.24219 3.5 2.58533 3.5 4.24219V7.24219H9.5V4.24219C9.5 2.58533 8.15685 1.24219 6.5 1.24219Z"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<svg width="40" height="26" viewBox="0 0 40 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="1.14258" y="0.50708" width="38.2857" height="24" rx="3.5" fill="#1F72CD" stroke="#C7C7C7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.31366 8.86157L6 16.4103H9.96691L10.4587 15.2067H11.5828L12.0746 16.4103H16.441V15.4917L16.8301 16.4103H19.0888L19.4779 15.4722V16.4103H28.5589L29.6631 15.2379L30.6971 16.4103L35.3613 16.42L32.0371 12.657L35.3613 8.86157H30.7694L29.6945 10.0122L28.6931 8.86157H18.8141L17.9658 10.81L17.0976 8.86157H13.139V9.74892L12.6986 8.86157H9.31366ZM10.0812 9.93314H12.0149L14.2128 15.0519V9.93314H16.3311L18.0287 13.6033L19.5933 9.93314H21.701V15.3498H20.4185L20.408 11.1053L18.5383 15.3498H17.3911L15.5109 11.1053V15.3498H12.8726L12.3724 14.1355H9.67018L9.17103 15.3488H7.75745L10.0812 9.93314ZM28.0891 9.93314H22.8743V15.3466H28.0084L29.6631 13.5525L31.2581 15.3466H32.9254L30.502 12.6556L32.9254 9.93314H31.3304L29.6841 11.7067L28.0891 9.93314ZM11.0218 10.8504L10.1315 13.0137H11.911L11.0218 10.8504ZM24.1622 12.0433V11.0545V11.0536H27.416L28.8358 12.6349L27.3531 14.2249H24.1622V13.1454H27.0071V12.0433H24.1622Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1,5 +0,0 @@
|
||||
<svg width="23" height="16" viewBox="0 0 23 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" width="22" height="16" rx="2" fill="white"/>
|
||||
<rect x="0.5" y="2.66406" width="22" height="2.66667" fill="#9FB8FF"/>
|
||||
<rect x="3" y="7.35938" width="17" height="2" rx="1" fill="#CEDBFF"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 16 KiB |
@ -1,11 +0,0 @@
|
||||
<svg width="40" height="25" viewBox="0 0 40 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.927734" y="0.5" width="38.2857" height="24" rx="3.5" fill="white" stroke="#C7C7C7"/>
|
||||
<path d="M21.7056 14.5831C23.1438 14.5831 24.3097 13.4173 24.3097 11.9791C24.3097 10.5409 23.1438 9.375 21.7056 9.375C20.2674 9.375 19.1016 10.5409 19.1016 11.9791C19.1016 13.4173 20.2674 14.5831 21.7056 14.5831Z" fill="#F26E21"/>
|
||||
<path d="M7.68056 13.2265C7.37371 13.5012 6.97776 13.6203 6.34895 13.6203H6.08805V10.3509H6.34895C6.97767 10.3509 7.35801 10.4622 7.68056 10.7509C8.0168 11.0475 8.21741 11.5066 8.21741 11.981C8.21741 12.4556 8.0168 12.9309 7.68056 13.2265ZM6.54397 9.51367H5.11523V14.4568H6.53679C7.2912 14.4568 7.83649 14.2799 8.31496 13.8862C8.88246 13.4194 9.21937 12.7153 9.21937 11.9875C9.21929 10.5281 8.11994 9.51367 6.54397 9.51367Z" fill="#0B161F"/>
|
||||
<path d="M9.66602 14.4568H10.6373V9.51367H9.66602V14.4568Z" fill="#0B161F"/>
|
||||
<path d="M13.0165 11.4102C12.4328 11.1954 12.2609 11.0542 12.2609 10.7886C12.2609 10.477 12.5668 10.2398 12.9859 10.2398C13.2775 10.2398 13.5162 10.3583 13.7715 10.6392L14.2787 9.98043C13.8607 9.61672 13.36 9.43164 12.8138 9.43164C11.9325 9.43164 11.2593 10.0395 11.2593 10.8463C11.2593 11.5292 11.5728 11.8773 12.4853 12.2042C12.8665 12.337 13.0603 12.4254 13.1578 12.4857C13.3519 12.612 13.4497 12.7891 13.4497 12.9967C13.4497 13.3976 13.1281 13.6935 12.694 13.6935C12.2306 13.6935 11.8572 13.4642 11.6327 13.0342L11.0059 13.6351C11.4533 14.2863 11.9915 14.5766 12.7321 14.5766C13.7408 14.5766 14.4505 13.9085 14.4505 12.9529C14.451 12.1667 14.1228 11.8108 13.0165 11.4102Z" fill="#0B161F"/>
|
||||
<path d="M14.7578 11.9872C14.7578 13.4416 15.9091 14.5682 17.3891 14.5682C17.8079 14.5682 18.166 14.486 18.6076 14.2797V13.1444C18.2185 13.5304 17.8744 13.6857 17.4335 13.6857C16.4544 13.6857 15.7591 12.9813 15.7591 11.9804C15.7591 11.032 16.4766 10.2829 17.3891 10.2829C17.8516 10.2829 18.2035 10.4457 18.6076 10.8389V9.70445C18.1819 9.49006 17.8298 9.40161 17.411 9.40161C15.939 9.40195 14.7578 10.551 14.7578 11.9872Z" fill="#0B161F"/>
|
||||
<path d="M26.4857 12.8341L25.155 9.51367H24.0938L26.2098 14.5834H26.7322L28.8854 9.51367H27.8313L26.4857 12.8341Z" fill="#0B161F"/>
|
||||
<path d="M29.3281 14.4568H32.0856V13.6203H30.2997V12.2847H32.0172V11.4481H30.2997V10.3509H32.0856V9.51367H29.3281V14.4568Z" fill="#0B161F"/>
|
||||
<path d="M33.9802 11.789H33.6971V10.2909H33.9955C34.6021 10.2909 34.9311 10.544 34.9311 11.0249C34.9311 11.5212 34.6021 11.789 33.9802 11.789ZM35.9308 10.9725C35.9308 10.0465 35.2887 9.51367 34.1668 9.51367H32.7246V14.4568H33.6968V12.4703H33.8244L35.1687 14.4568H36.3647L34.7944 12.3743C35.528 12.2262 35.9308 11.7291 35.9308 10.9725Z" fill="#0B161F"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@ -1,2 +0,0 @@
|
||||
export * from './Button'
|
||||
export * from './Modal'
|
||||
@ -1,6 +0,0 @@
|
||||
<svg width="40" height="26" viewBox="0 0 40 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.857422" y="0.50708" width="38.2857" height="24" rx="3.5" fill="white" stroke="#C7C7C7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.6198 19.2054C28.5208 19.2054 31.6831 16.0807 31.6831 12.2262C31.6831 8.37175 28.5208 5.24707 24.6198 5.24707C22.8715 5.24707 21.2715 5.87473 20.0381 6.91445C18.8048 5.87492 17.2049 5.24738 15.4568 5.24738C11.5559 5.24738 8.39355 8.37206 8.39355 12.2266C8.39355 16.081 11.5559 19.2057 15.4568 19.2057C17.2051 19.2057 18.8051 18.5781 20.0385 17.5383C21.2719 18.5779 22.8717 19.2054 24.6198 19.2054Z" fill="#ED0006"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0381 17.538C21.5568 16.2579 22.5198 14.353 22.5198 12.226C22.5198 10.0989 21.5568 8.19413 20.0381 6.91402C21.2715 5.87441 22.8714 5.24683 24.6196 5.24683C28.5205 5.24683 31.6828 8.37151 31.6828 12.226C31.6828 16.0805 28.5205 19.2052 24.6196 19.2052C22.8714 19.2052 21.2715 18.5776 20.0381 17.538Z" fill="#F9A000"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0383 17.5382C21.557 16.258 22.52 14.3533 22.52 12.2262C22.52 10.0992 21.557 8.19441 20.0383 6.91431C18.5196 8.19441 17.5566 10.0992 17.5566 12.2262C17.5566 14.3533 18.5196 16.258 20.0383 17.5382Z" fill="#FF5E00"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,18 +0,0 @@
|
||||
export const cardStyles = {
|
||||
base: {
|
||||
color: '#121620',
|
||||
lineHeight: '18px',
|
||||
fontSize: '16px',
|
||||
fontWeight: '400',
|
||||
fontFamily: 'SF Pro Text, system-ui, sans-serif',
|
||||
'::placeholder': {
|
||||
color: '#8E8E93',
|
||||
}
|
||||
},
|
||||
invalid: {
|
||||
color: '#FF5758',
|
||||
},
|
||||
empty: {
|
||||
fontWeight: '400',
|
||||
},
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<svg width="40" height="26" viewBox="0 0 40 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.571289" y="0.50708" width="38.2857" height="24" rx="3.5" fill="white" stroke="#C7C7C7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5123 16.6824H10.0603L8.22151 10.3638C8.13424 10.0731 7.94893 9.81616 7.67634 9.69505C6.99608 9.3907 6.24647 9.14849 5.42871 9.02633V8.78306H9.37881C9.92398 8.78306 10.3329 9.14849 10.401 9.57289L11.3551 14.1307L13.8059 8.78306H16.1899L12.5123 16.6824ZM17.5528 16.6824H15.2371L17.144 8.78306H19.4597L17.5528 16.6824ZM22.4557 10.9714C22.5238 10.5459 22.9327 10.3026 23.4098 10.3026C24.1594 10.2416 24.9759 10.3637 25.6574 10.667L26.0663 8.96626C25.3848 8.72299 24.6352 8.60083 23.9549 8.60083C21.7073 8.60083 20.0718 9.695 20.0718 11.2136C20.0718 12.3688 21.2303 12.9754 22.048 13.3408C22.9327 13.7052 23.2735 13.9485 23.2053 14.3129C23.2053 14.8594 22.5238 15.1027 21.8436 15.1027C21.0258 15.1027 20.2081 14.9205 19.4597 14.6162L19.0508 16.318C19.8685 16.6213 20.7532 16.7434 21.571 16.7434C24.0912 16.8034 25.6574 15.7103 25.6574 14.0696C25.6574 12.0034 22.4557 11.8823 22.4557 10.9714ZM33.7621 16.6824L31.9233 8.78306H29.9483C29.5394 8.78306 29.1305 9.02633 28.9942 9.3907L25.5893 16.6824H27.9732L28.449 15.5282H31.3781L31.6507 16.6824H33.7621ZM30.289 10.9106L30.9693 13.8877H29.0624L30.289 10.9106Z" fill="#172B85"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,5 +0,0 @@
|
||||
import gPaySafeCheckout from './Google-Pay.png'
|
||||
|
||||
export function GooglePayBanner(): JSX.Element {
|
||||
return <img src={gPaySafeCheckout} alt='Guaranteed safe checkout' />
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PaymentIntent } from '@chargebee/chargebee-js-types'
|
||||
import { SubscriptionReceipts, extractErrorMessage, useApi, useApiCall } from '@/api'
|
||||
import { usePayment, GooglePayButtonOptions } from '@/payment'
|
||||
import { useAuth } from '@/auth'
|
||||
import Loader, { LoaderColor } from '@/components/Loader'
|
||||
import ErrorText from '@/components/ErrorText'
|
||||
|
||||
const currencyCode = 'USD'
|
||||
const paymentMethod = 'google_pay'
|
||||
const buttonId = 'google-pay-btn'
|
||||
|
||||
interface GooglePayButtonProps {
|
||||
onSuccess: (receipt: SubscriptionReceipts.SubscriptionReceipt) => void
|
||||
onError: (error: Error) => void
|
||||
}
|
||||
|
||||
export function GooglePayButton({ onSuccess, onError }: GooglePayButtonProps): JSX.Element {
|
||||
const api = useApi()
|
||||
const { i18n } = useTranslation()
|
||||
const { token } = useAuth()
|
||||
const { googlePay } = usePayment()
|
||||
const [isMounting, setIsMounting] = useState<boolean>(true)
|
||||
const loadData = useCallback(() => {
|
||||
return api.createPaymentIntent({ token, paymentMethod, currencyCode })
|
||||
.then(({ payment_intent }) => payment_intent)
|
||||
}, [api, token])
|
||||
const { data, error, isPending } = useApiCall<PaymentIntent>(loadData)
|
||||
|
||||
if (error) console.error(error)
|
||||
|
||||
useEffect(() => {
|
||||
if (data === null) return
|
||||
const buttonOptions: GooglePayButtonOptions = {
|
||||
buttonColor: 'black',
|
||||
buttonType: 'plain',
|
||||
buttonLocale: i18n.language,
|
||||
buttonSizeMode: 'fill',
|
||||
}
|
||||
googlePay?.setPaymentIntent(data)
|
||||
googlePay?.mountPaymentButton(`#${buttonId}`, buttonOptions)
|
||||
.then(() => setIsMounting(false))
|
||||
.then(() => googlePay?.handlePayment())
|
||||
.then((result) => {
|
||||
console.log('Success payment by GooglePay', result)
|
||||
// TODO: implement api.createSubscriptionReceipt for GooglePay
|
||||
})
|
||||
.then(() => onSuccess({} as SubscriptionReceipts.SubscriptionReceipt))
|
||||
.catch((error: Error) => onError(error))
|
||||
}, [data, googlePay, i18n.language, onSuccess, onError])
|
||||
|
||||
return (
|
||||
<div id={buttonId} className='pay-btn'>
|
||||
{isPending || isMounting ? <FakeGPayButton /> : null}
|
||||
{error ? <ErrorText message={extractErrorMessage(error)} isShown={true} size='large'/> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FakeGPayButton() {
|
||||
return (
|
||||
<div className='gpay-button-fake-loader'>
|
||||
<Loader color={LoaderColor.White} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
Before Width: | Height: | Size: 74 KiB |
@ -1 +0,0 @@
|
||||
<svg width="41" height="17" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M19.526 2.635v4.083h2.518c.6 0 1.096-.202 1.488-.605.403-.402.605-.882.605-1.437 0-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0 5.52v4.736h-1.504V1.198h3.99c1.013 0 1.873.337 2.582 1.012.72.675 1.08 1.497 1.08 2.466 0 .991-.36 1.819-1.08 2.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668 2.287c0 .392.166.718.499.98.332.26.722.391 1.168.391.633 0 1.196-.234 1.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61 0-1.12.148-1.528.442-.409.294-.613.657-.613 1.093m1.946-5.815c1.112 0 1.989.297 2.633.89.642.594.964 1.408.964 2.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45 1.372-2.486 1.372-.882 0-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96 0-.828.313-1.486.94-1.976s1.463-.735 2.51-.735c.892 0 1.629.163 2.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132 2.132 0 0 0-1.455-.547c-.84 0-1.504.353-1.995 1.062l-1.324-.834c.73-1.045 1.81-1.568 3.238-1.568m11.853.262l-5.02 11.53H34.42l1.864-4.034-3.302-7.496h1.635l2.387 5.749h.032l2.322-5.75z" fill="#FFF"/><path d="M13.448 7.134c0-.473-.04-.93-.116-1.366H6.988v2.588h3.634a3.11 3.11 0 0 1-1.344 2.042v1.68h2.169c1.27-1.17 2.001-2.9 2.001-4.944" fill="#4285F4"/><path d="M6.988 13.7c1.816 0 3.344-.595 4.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754 0-3.244-1.182-3.776-2.774H.978v1.731a6.728 6.728 0 0 0 6.01 3.703" fill="#34A853"/><path d="M3.212 8.267a4.034 4.034 0 0 1 0-2.572V3.964H.978A6.678 6.678 0 0 0 .261 6.98c0 1.085.26 2.11.717 3.017l2.234-1.731z" fill="#FABB05"/><path d="M6.988 2.921c.992 0 1.88.34 2.58 1.008v.001l1.92-1.918C10.324.928 8.804.262 6.989.262a6.728 6.728 0 0 0-6.01 3.702l2.234 1.731c.532-1.592 2.022-2.774 3.776-2.774" fill="#E94235"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,2 +0,0 @@
|
||||
export * from './Banner'
|
||||
export * from './Button'
|
||||
@ -1,3 +0,0 @@
|
||||
export * from './ApplePay'
|
||||
export * from './GooglePay'
|
||||
export * from './Card'
|
||||
@ -44,10 +44,6 @@
|
||||
letter-spacing: 0.0008em;
|
||||
}
|
||||
|
||||
.payment-chargebee {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.payment-card-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@ -2,7 +2,6 @@ import { useTranslation } from "react-i18next";
|
||||
import styles from "./styles.module.css";
|
||||
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
||||
import TotalToday from "./TotalToday";
|
||||
// import ApplePayButton from "../StripePage/ApplePayButton";
|
||||
import MainButton from "../MainButton";
|
||||
import { useApi } from "@/api";
|
||||
import { useAuth } from "@/auth";
|
||||
|
||||
@ -8,7 +8,6 @@ import { store } from "./store";
|
||||
import { AuthProvider } from "./auth";
|
||||
import { ApiContext, createApi } from "./api";
|
||||
import { LegalContext, buildLegal } from "./legal";
|
||||
import { PaymentContext } from "./payment";
|
||||
import { getClientLocale, buildResources, fallbackLng } from "./locales";
|
||||
import App from "./components/App";
|
||||
|
||||
@ -35,7 +34,6 @@ const init = async () => {
|
||||
.use(initReactI18next)
|
||||
.use(new ReactPostprocessor())
|
||||
.init(options);
|
||||
window.Chargebee.init(config.chargebee);
|
||||
|
||||
const isProduction = import.meta.env.MODE === "production";
|
||||
|
||||
@ -72,11 +70,7 @@ const init = async () => {
|
||||
<ApiContext.Provider value={api}>
|
||||
<AuthProvider>
|
||||
<LegalContext.Provider value={legal}>
|
||||
<PaymentContext.Provider
|
||||
value={window.Chargebee.getInstance()}
|
||||
>
|
||||
<App />
|
||||
</PaymentContext.Provider>
|
||||
<App />
|
||||
</LegalContext.Provider>
|
||||
</AuthProvider>
|
||||
</ApiContext.Provider>
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
import { createContext } from 'react'
|
||||
import { ChargebeeInstance } from '@chargebee/chargebee-js-types'
|
||||
|
||||
export const PaymentContext = createContext<ChargebeeInstance>({} as ChargebeeInstance)
|
||||
@ -1,3 +0,0 @@
|
||||
export * from './PaymentContext'
|
||||
export * from './usePayment'
|
||||
export * from './types'
|
||||
@ -1,43 +0,0 @@
|
||||
import { PaymentIntent } from '@chargebee/chargebee-js-types'
|
||||
|
||||
interface Handler {
|
||||
handlePayment: () => Promise<PaymentIntent>
|
||||
setPaymentIntent: (paymentIntent: PaymentIntent) => void
|
||||
}
|
||||
|
||||
export interface GooglePayButtonOptions {
|
||||
buttonColor: 'default' | 'black' | 'white'
|
||||
buttonType: 'long' | 'short' | 'book' | 'buy' | 'checkout' | 'donate' | 'order' | 'pay' | 'plain' | 'subscribe'
|
||||
buttonSizeMode: 'static' | 'fill'
|
||||
buttonLocale: string
|
||||
}
|
||||
|
||||
export interface PaymentOptions {
|
||||
requestPayerEmail: boolean
|
||||
requestBillingAddress: boolean
|
||||
requestShippingAddress: boolean
|
||||
}
|
||||
|
||||
export interface ApplePayButtonOptions {
|
||||
locale: string
|
||||
buttonColor: 'black' | 'white' | 'white-outline'
|
||||
buttonType: 'add-money' | 'book' | 'buy' | 'check-out' | 'continue' | 'contribute' | 'donate' | 'order' | 'pay' | 'plain' | 'reload' | 'rent' | 'set-up' | 'subscribe' | 'support' | 'tip' | 'top-up'
|
||||
}
|
||||
|
||||
interface ApplePay extends Handler {
|
||||
canMakePayments: () => boolean
|
||||
mountPaymentButton: (selector: string, options?: ApplePayButtonOptions) => Promise<void>
|
||||
}
|
||||
|
||||
interface GooglePay extends Handler {
|
||||
getPaymentIntent: () => PaymentIntent
|
||||
updatePaymentIntent: (paymentIntent: PaymentIntent) => void
|
||||
mountPaymentButton: (
|
||||
selector: string,
|
||||
buttonOptions?: GooglePayButtonOptions,
|
||||
paymentOptions?: PaymentOptions
|
||||
) => Promise<void>
|
||||
}
|
||||
|
||||
export type ApplePayHandler = ApplePay | null
|
||||
export type GooglePayHandler = GooglePay | null
|
||||
@ -1,21 +0,0 @@
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { PaymentContext } from './PaymentContext'
|
||||
import { ApplePayHandler, GooglePayHandler } from './types'
|
||||
|
||||
export const usePayment = () => {
|
||||
const chargebee = useContext(PaymentContext)
|
||||
const [googlePay, setGooglePay] = useState<GooglePayHandler>(null)
|
||||
const [applePay, setApplePay] = useState<ApplePayHandler>(null)
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
chargebee.load('google-pay'),
|
||||
chargebee.load('apple-pay'),
|
||||
]).then(([googlePay, applePay]) => {
|
||||
setGooglePay(googlePay)
|
||||
setApplePay(applePay)
|
||||
})
|
||||
}, [chargebee])
|
||||
|
||||
return { chargebee, googlePay, applePay }
|
||||
}
|
||||
@ -1,11 +1,3 @@
|
||||
import { Chargebee } from "@chargebee/chargebee-js-types";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
Chargebee: typeof Chargebee;
|
||||
}
|
||||
}
|
||||
|
||||
export enum EDirectionOnboarding {
|
||||
LEFT = "left",
|
||||
RIGHT = "right",
|
||||
|
||||