Fix stripe. Remove fetching prices in getServerSideProps

This commit is contained in:
2023-03-05 23:04:06 +04:00
parent cdabf79e92
commit d80e20d62f
6 changed files with 66 additions and 40 deletions
+18 -5
View File
@@ -1,4 +1,4 @@
import {useState} from 'react' import {useState, useEffect} from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { import {
PaymentElement, PaymentElement,
@@ -9,11 +9,11 @@ import {Button, Container, LinearProgress, Paper} from '@mui/material'
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001' const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
export default function CheckoutForm({prices, validMontant, setError, isLoading, setIsLoading}) { export default function CheckoutForm({validMontant, setError, isLoading, setIsLoading}) {
const stripe = useStripe() const stripe = useStripe()
const elements = useElements() const elements = useElements()
const [isPaymentLoading, setIsPaymentLoading] = useState(false) const [isPaymentLoading, setIsPaymentLoading] = useState(false)
const amount = prices.find(({id}) => id === validMontant).unit_amount const [prices, setPrices] = useState([])
const handleSubmit = async event => { const handleSubmit = async event => {
event.preventDefault() event.preventDefault()
@@ -44,13 +44,27 @@ export default function CheckoutForm({prices, validMontant, setError, isLoading,
setIsLoading(false) setIsLoading(false)
} }
useEffect(() => {
const fetchPrices = async () => {
try {
const response = await fetch(`${SITE_URL}/stripe/dons-list`)
const pricesList = await response.json()
setPrices(pricesList)
} catch (error) {
console.error('error', error)
}
}
fetchPrices()
}, [prices])
return ( return (
<Container maxWidth='sm' sx={{marginBottom: 1}}> <Container maxWidth='sm' sx={{marginBottom: 1}}>
<Paper sx={{padding: 2, marginTop: 3}}> <Paper sx={{padding: 2, marginTop: 3}}>
<PaymentElement id='payment-element' onReady={handleReady} /> <PaymentElement id='payment-element' onReady={handleReady} />
{!isLoading && ( {!isLoading && (
<Button fullWidth sx={{marginTop: 2}} variant='outlined' disabled={isPaymentLoading || !stripe || !elements} id='submit' onClick={handleSubmit}> <Button fullWidth sx={{marginTop: 2}} variant='outlined' disabled={isPaymentLoading || !stripe || !elements} id='submit' onClick={handleSubmit}>
Valider le don de&nbsp;<strong>{amount / 100} euros</strong> Valider le don de&nbsp;<strong>{prices.find(({id}) => id === validMontant).unit_amount / 100} euros</strong>
</Button> </Button>
)} )}
{isPaymentLoading && ( {isPaymentLoading && (
@@ -63,7 +77,6 @@ export default function CheckoutForm({prices, validMontant, setError, isLoading,
CheckoutForm.propTypes = { CheckoutForm.propTypes = {
validMontant: PropTypes.string.isRequired, validMontant: PropTypes.string.isRequired,
prices: PropTypes.array.isRequired,
setError: PropTypes.func.isRequired, setError: PropTypes.func.isRequired,
isLoading: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired,
setIsLoading: PropTypes.func.isRequired setIsLoading: PropTypes.func.isRequired
+26 -4
View File
@@ -1,14 +1,33 @@
import {useState, useEffect} from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import ToggleButton from '@mui/material/ToggleButton' import ToggleButton from '@mui/material/ToggleButton'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup' import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import {Box} from '@mui/material' import {Box} from '@mui/material'
import CircularProgress from '@mui/material/CircularProgress'
export default function Montant({selectedMontant, setSelectedMontant, validMontant, prices}) { const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
export default function Montant({selectedMontant, setSelectedMontant, validMontant}) {
const [prices, setPrices] = useState(null)
const handleChange = (event, newMontant) => { const handleChange = (event, newMontant) => {
setSelectedMontant(newMontant) setSelectedMontant(newMontant)
} }
useEffect(() => {
const fetchPrices = async () => {
try {
const response = await fetch(`${SITE_URL}/stripe/dons-list`)
const pricesList = await response.json()
setPrices(pricesList)
} catch (error) {
console.error('error', error)
}
}
fetchPrices()
}, [prices])
return ( return (
<Box> <Box>
<Typography marginTop={1} variant='button' component='div'> <Typography marginTop={1} variant='button' component='div'>
@@ -22,7 +41,11 @@ export default function Montant({selectedMontant, setSelectedMontant, validMonta
value={selectedMontant} value={selectedMontant}
onChange={handleChange} onChange={handleChange}
> >
{prices.map(r => ( {!prices && (
<CircularProgress color='primary' size={20} />
)}
{prices && prices.map(r => (
<ToggleButton key={r.id} value={r.id}>{r.unit_amount / 100} </ToggleButton> <ToggleButton key={r.id} value={r.id}>{r.unit_amount / 100} </ToggleButton>
))} ))}
@@ -39,6 +62,5 @@ Montant.defaultProps = {
Montant.propTypes = { Montant.propTypes = {
selectedMontant: PropTypes.string, selectedMontant: PropTypes.string,
setSelectedMontant: PropTypes.func.isRequired, setSelectedMontant: PropTypes.func.isRequired,
validMontant: PropTypes.string, validMontant: PropTypes.string
prices: PropTypes.array.isRequired
} }
+3 -9
View File
@@ -15,10 +15,7 @@ import {appearance} from '../../lib/utils/stripe-style'
import CheckoutForm from './checkout-form' import CheckoutForm from './checkout-form'
import StripeDialog from './stripe-dialog' import StripeDialog from './stripe-dialog'
const stripePromise = loadStripe( const STRIPE_PUBLIC_KEY = process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY
process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY
)
const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID
const LIBERAPAY_DONATE = process.env.NEXT_PUBLIC_LIBERAPAY_DONATE const LIBERAPAY_DONATE = process.env.NEXT_PUBLIC_LIBERAPAY_DONATE
@@ -55,7 +52,7 @@ function a11yProps(index) {
} }
} }
export default function PaymentMethod({isLoading, paymentMethod, setPaymentMethod, selectedMontant, setSelectedMontant, validMontant, setValidMontant, prices, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, clientSecret}) { export default function PaymentMethod({isLoading, paymentMethod, setPaymentMethod, selectedMontant, setSelectedMontant, validMontant, setValidMontant, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, clientSecret}) {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const options = { const options = {
@@ -114,7 +111,6 @@ export default function PaymentMethod({isLoading, paymentMethod, setPaymentMetho
setSelectedMontant={setSelectedMontant} setSelectedMontant={setSelectedMontant}
validMontant={validMontant} validMontant={validMontant}
setValidMontant={setValidMontant} setValidMontant={setValidMontant}
prices={prices}
paymentIntent={paymentIntent} paymentIntent={paymentIntent}
setClientSecret={setClientSecret} setClientSecret={setClientSecret}
setPaymentIntent={setPaymentIntent} setPaymentIntent={setPaymentIntent}
@@ -126,9 +122,8 @@ export default function PaymentMethod({isLoading, paymentMethod, setPaymentMetho
isLoading={isLoading} isLoading={isLoading}
> >
{clientSecret && validMontant && paymentMethod === 2 && ( {clientSecret && validMontant && paymentMethod === 2 && (
<Elements options={options} stripe={stripePromise}> <Elements options={options} stripe={loadStripe(STRIPE_PUBLIC_KEY)}>
<CheckoutForm <CheckoutForm
prices={prices}
validMontant={validMontant} validMontant={validMontant}
setError={setError} setError={setError}
isLoading={isLoading} isLoading={isLoading}
@@ -159,7 +154,6 @@ PaymentMethod.propTypes = {
setSelectedMontant: PropTypes.func.isRequired, setSelectedMontant: PropTypes.func.isRequired,
validMontant: PropTypes.string, validMontant: PropTypes.string,
setValidMontant: PropTypes.func.isRequired, setValidMontant: PropTypes.func.isRequired,
prices: PropTypes.array.isRequired,
paymentIntent: PropTypes.string, paymentIntent: PropTypes.string,
setClientSecret: PropTypes.func.isRequired, setClientSecret: PropTypes.func.isRequired,
setPaymentIntent: PropTypes.func.isRequired, setPaymentIntent: PropTypes.func.isRequired,
+1 -3
View File
@@ -14,7 +14,6 @@ export default function StripeDialog({
setSelectedMontant, setSelectedMontant,
validMontant, validMontant,
setValidMontant, setValidMontant,
prices,
paymentIntent, paymentIntent,
setClientSecret, setClientSecret,
setPaymentIntent, setPaymentIntent,
@@ -46,7 +45,6 @@ export default function StripeDialog({
setSelectedMontant={setSelectedMontant} setSelectedMontant={setSelectedMontant}
validMontant={validMontant} validMontant={validMontant}
setValidMontant={setValidMontant} setValidMontant={setValidMontant}
prices={prices}
paymentIntent={paymentIntent} paymentIntent={paymentIntent}
setClientSecret={setClientSecret} setClientSecret={setClientSecret}
setPaymentIntent={setPaymentIntent} setPaymentIntent={setPaymentIntent}
@@ -56,6 +54,7 @@ export default function StripeDialog({
error={error} error={error}
setError={setError} setError={setError}
isLoading={isLoading} isLoading={isLoading}
handleClose={handleClose}
/> />
{children} {children}
</DialogContent> </DialogContent>
@@ -81,7 +80,6 @@ StripeDialog.propTypes = {
setSelectedMontant: PropTypes.func.isRequired, setSelectedMontant: PropTypes.func.isRequired,
validMontant: PropTypes.string, validMontant: PropTypes.string,
setValidMontant: PropTypes.func.isRequired, setValidMontant: PropTypes.func.isRequired,
prices: PropTypes.array.isRequired,
paymentIntent: PropTypes.string, paymentIntent: PropTypes.string,
setClientSecret: PropTypes.func.isRequired, setClientSecret: PropTypes.func.isRequired,
setPaymentIntent: PropTypes.func.isRequired, setPaymentIntent: PropTypes.func.isRequired,
+15 -12
View File
@@ -12,7 +12,7 @@ import {validateEmail} from '../../lib/utils/emails'
import Email from './email' import Email from './email'
import Montant from './montant' import Montant from './montant'
export default function StripePayment({isLoading, selectedMontant, setSelectedMontant, validMontant, setValidMontant, prices, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError}) { export default function StripePayment({isLoading, selectedMontant, setSelectedMontant, validMontant, setValidMontant, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, handleClose}) {
const cancelPayment = async () => { const cancelPayment = async () => {
setClientEmail('') setClientEmail('')
setIsLoading(false) setIsLoading(false)
@@ -29,9 +29,14 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
} }
const handleCancel = async () => { const handleCancel = async () => {
setValidMontant(null) if (validMontant) {
setSelectedMontant(null) setValidMontant(null)
await cancelPayment() setSelectedMontant(null)
await cancelPayment()
handleClose()
} else {
handleClose()
}
} }
const handleClick = () => { const handleClick = () => {
@@ -59,7 +64,6 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
setSelectedMontant={setSelectedMontant} setSelectedMontant={setSelectedMontant}
validMontant={validMontant} validMontant={validMontant}
setValidMontant={setValidMontant} setValidMontant={setValidMontant}
prices={prices}
paymentIntent={paymentIntent} paymentIntent={paymentIntent}
setClientSecret={setClientSecret} setClientSecret={setClientSecret}
setPaymentIntent={setPaymentIntent} setPaymentIntent={setPaymentIntent}
@@ -71,11 +75,10 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
<Button disabled={Boolean(validMontant) || Boolean(!selectedMontant)} variant='contained' onClick={handleClick}> <Button disabled={Boolean(validMontant) || Boolean(!selectedMontant)} variant='contained' onClick={handleClick}>
Valider les informations Valider les informations
</Button> </Button>
{validMontant && (
<Button disabled={Boolean(!validMontant)} color='secondary' variant='contained' onClick={handleCancel}> <Button color='secondary' variant='contained' onClick={handleCancel}>
Annuler Annuler
</Button> </Button>
)}
</Stack> </Stack>
</> </>
{isLoading && ( {isLoading && (
@@ -102,7 +105,6 @@ StripePayment.propTypes = {
setSelectedMontant: PropTypes.func.isRequired, setSelectedMontant: PropTypes.func.isRequired,
validMontant: PropTypes.string, validMontant: PropTypes.string,
setValidMontant: PropTypes.func.isRequired, setValidMontant: PropTypes.func.isRequired,
prices: PropTypes.array.isRequired,
paymentIntent: PropTypes.string, paymentIntent: PropTypes.string,
setClientSecret: PropTypes.func.isRequired, setClientSecret: PropTypes.func.isRequired,
setPaymentIntent: PropTypes.func.isRequired, setPaymentIntent: PropTypes.func.isRequired,
@@ -110,5 +112,6 @@ StripePayment.propTypes = {
setClientEmail: PropTypes.func.isRequired, setClientEmail: PropTypes.func.isRequired,
clientEmail: PropTypes.string, clientEmail: PropTypes.string,
error: PropTypes.string, error: PropTypes.string,
setError: PropTypes.func.isRequired setError: PropTypes.func.isRequired,
handleClose: PropTypes.func.isRequired
} }
+3 -7
View File
@@ -16,7 +16,7 @@ const Alert = forwardRef(function Alert(props, ref) {
return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} /> return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
}) })
export default function Soutyen({prices, paymentStatus}) { export default function Soutyen({paymentStatus}) {
const router = useRouter() const router = useRouter()
const scrollEvent = useRef(null) const scrollEvent = useRef(null)
const [clientSecret, setClientSecret] = useState(null) const [clientSecret, setClientSecret] = useState(null)
@@ -60,7 +60,7 @@ export default function Soutyen({prices, paymentStatus}) {
} }
useEffect(() => { useEffect(() => {
if (paymentMethod !== 0) { if (paymentMethod !== 2) {
setClientEmail('') setClientEmail('')
setClientSecret(null) setClientSecret(null)
setSelectedMontant(null) setSelectedMontant(null)
@@ -124,7 +124,7 @@ export default function Soutyen({prices, paymentStatus}) {
> >
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}> <Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
<Box sx={{flexGrow: 1, marginTop: 1, marginBottom: 10}}> <Box sx={{flexGrow: 1, marginTop: 1, marginBottom: 10}}>
<Container sx={{marginTop: 1}}> <Container sx={{marginTop: 3}}>
<Typography gutterBottom sx={{fontWeight: 'bold'}} textAlign='center' variant='h4' component='h1'> <Typography gutterBottom sx={{fontWeight: 'bold'}} textAlign='center' variant='h4' component='h1'>
Soutenir Organisation KA Internationale ! Soutenir Organisation KA Internationale !
</Typography> </Typography>
@@ -138,7 +138,6 @@ export default function Soutyen({prices, paymentStatus}) {
setSelectedMontant={setSelectedMontant} setSelectedMontant={setSelectedMontant}
validMontant={validMontant} validMontant={validMontant}
setValidMontant={setValidMontant} setValidMontant={setValidMontant}
prices={prices}
isLoading={isLoading} isLoading={isLoading}
paymentIntent={paymentIntent} paymentIntent={paymentIntent}
clientSecret={clientSecret} clientSecret={clientSecret}
@@ -173,13 +172,11 @@ Soutyen.defaultProps = {
} }
Soutyen.propTypes = { Soutyen.propTypes = {
prices: PropTypes.array.isRequired,
paymentStatus: PropTypes.string paymentStatus: PropTypes.string
} }
export async function getServerSideProps({query}) { export async function getServerSideProps({query}) {
const {payment_intent, payment_intent_client_secret} = query const {payment_intent, payment_intent_client_secret} = query
const prices = await fetch(`${SITE_URL}/stripe/dons-list`)
let payment let payment
if (payment_intent && payment_intent_client_secret) { if (payment_intent && payment_intent_client_secret) {
const paymentResponse = await fetch(`${SITE_URL}/stripe/check-payment`, { const paymentResponse = await fetch(`${SITE_URL}/stripe/check-payment`, {
@@ -198,7 +195,6 @@ export async function getServerSideProps({query}) {
return { return {
props: { props: {
prices: await prices.json(),
paymentStatus: payment?.status || null paymentStatus: payment?.status || null
} }
} }