#FestiveOx
1 messages · Page 1 of 1 (latest)
import React, { useEffect, useState } from "react"
import { loadStripe } from "@stripe/stripe-js"
import {
Elements,
PaymentElement,
useStripe,
useElements,
} from "@stripe/react-stripe-js"
import { CircularProgress } from "@mui/material"
import Typography from "@mui/material/Typography"
import { STRIPE_PUBLISHABLE_KEY } from "utils/environment"
let redirectTimeout
// Make sure to call loadStripe outside of a component’s render to avoid
// recreating the Stripe object on every render.
// This is your test publishable API key.
const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY)
const Checkout = ({ clientSecret, orderMutation, paymentIntentId }) => {
const appearance = {
theme: "stripe",
}
const options = {
clientSecret,
appearance,
}
return (
<div
className="App"
style={{ background: "#ffffff", borderRadius: "10px" }}>
{clientSecret ? (
<Elements options={options} stripe={stripePromise}>
<CheckoutForm
orderMutation={orderMutation}
paymentIntentId={paymentIntentId}
/>
</Elements>
) : (
<div
style={{
justifyContent: "center",
alignItems: "center",
display: "flex",
padding: 3,
height: 200,
}}>
<CircularProgress />
</div>
)}
</div>
)
}
export default Checkout
And the CheckoutForm Component:
const CheckoutForm = () => {
const stripe = useStripe()
const elements = useElements()
const [message, setMessage] = useState(null)
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
if (!stripe) {
return
}
return () => {
clearTimeout(redirectTimeout)
}
}, [stripe])
const handleSubmit = async (e) => {
e.preventDefault()
if (!stripe || !elements) {
// Stripe.js has not yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return
}
setIsLoading(true)
console.log("elements: ", elements)
try {
const result = await stripe.createPaymentMethod({
type: "card",
card: elements,
billing_details: {
// Include any additional collected billing details.
name: "Jenny Rosen",
},
})
console.log(result)
} catch (e) {
console.log(e)
}
setIsLoading(false)
}
return (
<form id="payment-form" onSubmit={handleSubmit}>
<PaymentElement
id="payment-element"
onReady={() => setIsLoading(false)}
/>
{isLoading || !stripe || !elements ? (
<div
style={{
justifyContent: "center",
alignItems: "center",
display: "flex",
padding: 3,
height: 200,
}}>
<CircularProgress />
</div>
) : (
<>
<button disabled={isLoading || !stripe || !elements} id="submit">
<span id="button-text">Pay now</span>
</button>
<Typography variant="caption" color="black">
By purchasing you agree to our Terms of Service and Privacy Policy.
</Typography>
</>
)}
{/* Show any error or success messages */}
{message && <div id="payment-message">{message}</div>}
</form>
)
}
Looking into it now
I'm just trying to create a payment method using the new Stripe Element as recommended by https://stripe.com/docs/payments/accept-a-payment-synchronously#web-collect-card-details
Thanks so much @quiet locust !
stripe.createPaymentMethod doesn't support passing Payment Element as a parameter. It only supports individual elements such as Card Element.
If you wish to use stripe.createPaymentMethod to create card payment method, Card Element is recommended as mentioned in the doc you shared
ah interesting because in the top of the page it says Stripe recommends using the newer Payment Element instead of the Card Element. It allows you to accept multiple payment methods with a single Element. Learn more about when to use the Card Element and Payment Element. So I figured the tutorial recommended to use the newer Payment Element
Ah I see! If you click the link on Payment Element, it will redirect to Payment Element documentation with a different integration approach from the doc you're in.
It doesn't mean that this "Accept card payments without webhooks" doc supports Payment Element
Could you share what you're trying to achieve?
Ahh gotcha!
I'm trying to implement something so that I can capture the payment in the server after some logic has been run
Basically I want to:
Get Payment in client -> Run some server logic -> If succeed with the server logic charge the credit card
Not charge the credit card before I run the server logic because if the server logic fails I want to reject the payment so that I don't charge users for a product that can't be fulfilled
Thanks for sharing the details. This doc will be something that you're looking for in Payment Element: https://stripe.com/docs/payments/run-custom-actions-before-confirmation
This feature is still in beta and you'll need to sign up for the access.
Interesting, and can anyone have access? Are there any other alternatives just in case? Would setupIntent be an option?
I'd recommend clicking on contact us to check the access.
If you're going to charge the payment immediately after using SetupIntent, we generally don't recommend it.
Both SetupIntent and PaymentIntent can trigger authentication, and it might lead to a bad customer experience to authenticate two times for same purchase.
The last recommendation will then be the doc you shared: https://stripe.com/docs/payments/accept-a-payment-synchronously
Ok perfect! I will wait for the response on the beta feature! Thanks so much!
No problem! Happy to help 😄
Hi @quiet locust sorry to bother you again. How about this one? https://stripe.com/docs/payments/place-a-hold-on-a-payment-method
Could I use this to achieve what I want?
Placing a hold means that it will authorise the amount on the customer's card, but the fund is not deducted yet. Customer might see an amount hold on his card in his bank website/app. Capture refers to amount deducted from customer's card with authorised amount. This flow is usually to reserve the funds from customer card and deduct at later time.
The common use case will be hotels authorise a payment in full before a guest arrives, then capture the money when the guest checks out.
Placing a hold is generally not recommended for running custom logic since it might give your customer a bad experience. Customer would have performed authentication during the authorising (placing a hold) phase. If your custom logic fails, customer might wonder why such authorisation is performed in the first place.
Hmm I'm not too worried about the user experience given that situation, but I see what you mean!
Again thanks so much for your knowledge and help!
No problem! Happy to help 😄