2023-07-30 18:52:32 +02:00
|
|
|
import { stripeConfig } from 'shared/config/stripe.mjs'
|
2023-07-30 18:21:24 +02:00
|
|
|
import { useEffect, useState } from 'react'
|
|
|
|
import { useTheme } from 'shared/hooks/use-theme.mjs'
|
|
|
|
import { Elements, PaymentElement } from '@stripe/react-stripe-js'
|
|
|
|
import { loadStripe } from '@stripe/stripe-js'
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The stripe API docs will emphasize to always handle this server-side because
|
|
|
|
* doing this client-side allows nefarious users to modify the payment amount.
|
|
|
|
* Which is great advice, but FreeSewing uses a pay-whatever-you-want model so
|
|
|
|
* if people want to muck about with JS to change the amount rather than change
|
|
|
|
* it in the input field for the amount, let them.
|
|
|
|
*
|
|
|
|
* This is also why we need to use fetch and talk to the API directly, because
|
|
|
|
* the stripe client-side SDK does not include this functionality.
|
|
|
|
*/
|
|
|
|
const createPaymentIntent = async ({ amount, currency }) => {
|
|
|
|
const body = new URLSearchParams()
|
|
|
|
body.append('amount', amount)
|
|
|
|
body.append('currency', currency)
|
|
|
|
|
|
|
|
return await fetch('https://api.stripe.com/v1/payment_intents', {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
2023-07-30 18:52:32 +02:00
|
|
|
authorization: `Bearer ${stripeConfig.apiKey}`,
|
2023-07-30 18:21:24 +02:00
|
|
|
},
|
|
|
|
body,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-07-30 18:52:32 +02:00
|
|
|
export const Payment = ({ amount = 2500, currency = 'eur' }) => {
|
2023-07-30 18:21:24 +02:00
|
|
|
const appearance = useTheme().stripe
|
|
|
|
const [stripe, setStripe] = useState(false)
|
|
|
|
const [intent, setIntent] = useState(false)
|
|
|
|
const options = intent
|
|
|
|
? {
|
|
|
|
mode: 'payment',
|
|
|
|
layout: {
|
|
|
|
type: 'accordion',
|
|
|
|
radios: true,
|
|
|
|
spacedAccordianItems: true,
|
|
|
|
},
|
|
|
|
business: {
|
|
|
|
name: 'FreeSewing',
|
|
|
|
},
|
|
|
|
amount,
|
|
|
|
currency,
|
|
|
|
appearance,
|
|
|
|
}
|
|
|
|
: null
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const getPaymentIntent = async () => {
|
2023-07-30 18:52:32 +02:00
|
|
|
const stripeClient = await loadStripe(stripeConfig.apiKey)
|
2023-07-30 18:21:24 +02:00
|
|
|
const result = await createPaymentIntent({ amount, currency })
|
|
|
|
const json = await result.json()
|
|
|
|
setStripe(stripeClient)
|
|
|
|
setIntent(json)
|
|
|
|
}
|
|
|
|
getPaymentIntent()
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
return intent ? (
|
|
|
|
<Elements stripe={stripe} options={options} layout="accordion">
|
|
|
|
<form>
|
|
|
|
<PaymentElement options={options} />
|
2023-07-30 18:52:32 +02:00
|
|
|
<pre>{JSON.stringify(intent, null, 2)}</pre>
|
2023-07-30 18:21:24 +02:00
|
|
|
</form>
|
|
|
|
</Elements>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<p>One moment please...</p>
|
|
|
|
<pre>{JSON.stringify(options, null, 2)}</pre>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
//<pre>{JSON.stringify(options, null ,2)}</pre>
|
|
|
|
//<pre>{JSON.stringify(intent, null ,2)}</pre>
|