#FestiveOx

1 messages · Page 1 of 1 (latest)

graceful coralBOT
hoary creek
#
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>
  )
}
quiet locust
#

Looking into it now

hoary creek
#

Thanks so much @quiet locust !

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

hoary creek
#

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

quiet locust
#

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?

hoary creek
#

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

quiet locust
hoary creek
#

Interesting, and can anyone have access? Are there any other alternatives just in case? Would setupIntent be an option?

quiet locust
#

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.

hoary creek
#

Ok perfect! I will wait for the response on the beta feature! Thanks so much!

quiet locust
#

No problem! Happy to help 😄

hoary creek
#

Could I use this to achieve what I want?

quiet locust
#

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.

hoary creek
#

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!

quiet locust
#

No problem! Happy to help 😄