#FKaiB

1 messages ยท Page 1 of 1 (latest)

sand drumBOT
blissful quail
#

Where is your PaymentElement created? I don't see it in your code

river dove
#
    // Fetch the clientSecret from your server here and set the state
    // For example:
    fetch("http://localhost:4242/create-payment-intent", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ items: [{ id: "your-item-id" }] }),
    })
      .then((res) => res.json())
      .then((data) => {
        setClientSecret(data.clientSecret);
      });
  }, []);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    if (!stripe || !elements || !clientSecret) {
      // Stripe.js has not yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }

    setIsLoading(true);

    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        // Make sure to change this to your payment completion page
        return_url: "http://localhost:3000",
      },
    });
    
    if (error.type === "card_error" || error.type === "validation_error") {
      setMessage(error.message as string);
    } else {
      setMessage("An unexpected error occurred.");
    }

    setIsLoading(false);
  };

  const paymentElementOptions = {
    layout: "tabs",
  };

  return (
    <form id="payment-form" onSubmit={handleSubmit}>
      <LinkAuthenticationElement
        id="link-authentication-element"
        onChange={(e) => setEmail(e.value.email)}
      />
      <PaymentElement
        id="payment-element"
        options={paymentElementOptions as StripePaymentElementOptions}
      />
      <button disabled={isLoading || !stripe || !elements} id="submit">
        <span id="button-text">
          {isLoading ? <div className="spinner" id="spinner"></div> : "Pay now"}
        </span>
      </button>
      {/* Show any error or success messages */}
      {message && <div id="payment-message">{message}</div>}
    </form>
  );
}```

I use it in the component CheckoutForm. Above is part of the code.
blissful quail
#

How does your <Elements> link with <CheckoutForm>? <CheckoutForm> should be wrapped within <Elements>, but I don't see it in your code

#

In addition, you shouldn't need to create Payment Intent again in CheckoutForm

#

It should be something like:

<div className="App">
  {clientSecret && (
    <Elements options={options} stripe={stripePromise}>
      <CheckoutForm />
    </Elements>
  )}
</div>
river dove
#

I have the CheckoutForm as a grand child of the Chatspert component. Chatspert -> BillingPopUp -> CheckoutForm.

#

and the <Chatspert > component is wrapped in <Elements>

#

does <ChecoutForm> have to directly be wrapped by <Elements>?

#

I also used the exmple from the quickstart guide

blissful quail
#

Not necessary, but it depends on how your React components are implemented

#

If you try to put <CheckoutForm> directly under <Elements>, does it work?

river dove
#

I tried

<Elements options={options} stripe={stripePromise}>
  <CheckoutForm />
</Elements>```

Inside the <BillingPopUp> file but I still get the same error.
blissful quail
#

How is your <BillingPopUp> set? How is it related to <Elements> and <CheckoutForm>? I don't have full visibility of how your components, so can't tell where goes wrong

river dove
#

let me go back several steps. So I was following the quickstart guide and had "options" defined as below just how it was done in the example code.

const appearance = {
   theme: "stripe",
 };
const options = {
    clientSecret,
    appearance,
 };```
However in typescript I was getting this error

Type '{ clientSecret: string; appearance: { theme: string; }; }' is not assignable to type 'StripeElementsOptions | undefined'.
Type '{ clientSecret: string; appearance: { theme: string; }; }' is not assignable to type 'StripeElementsOptionsMode'.
Types of property 'clientSecret' are incompatible.
Type 'string' is not assignable to type 'undefined'.


This is why I got rid of the "apperance" variiable which seems to get rid of the error. But now in the console, I am getting the error shared earlier in the thread. I believe for some reason, the "clientSecret" variable is not read correctly in <Elements>. I confirmed that the clientSecret does display the correct clientSecret when console logging.
river dove
blissful quail
#

Which version of @stripe/react-stripe-js are you using?

#

From your options parameter and <Elements>, the setting look correct

river dove
#

^2.1.0

blissful quail
#

Can you share the reproducible code that I can run? From the partial codes you shared, I don't have full visibility how your app works

river dove
#

I will make one right now

blissful quail
#

๐Ÿ‘

river dove
#

You have to replace the "CHANGE_ME" in App.tsx and sever.py to your API key

#

thanks for doing this btw. I am really stuck and I needed help

blissful quail
#

In the code you shared, I don't see <Elements> being used in App.tsx, BillingPopUp.tsx, Chatpert.tsx or CheckoutForm.tsx

#

This is what I received:

river dove
#

oop sorry. it should be

  <Elements options={options} stripe={stripePromise}>
    <Chatspert />
  </Elements>
}

in <Route>

blissful quail
#

When I hardcoded clientSecret to an actual client secret, it works:
(with import { StripeElementsOptions } from '@stripe/stripe-js';)

  const options: StripeElementsOptions = {
    clientSecret: "pi_3MwcAJF3hM0gtZIC0C07NY5Z_secret_jAoZ3j7863i6kmoJ1PcBTlVM6",
    appearance: {
      theme: 'stripe'
    },
  };
#

It seems like the elements is rendered before client secret is created

#

After I modify your code to:

            {clientSecret && <Route path="/" element={
              <Elements options={options} stripe={stripePromise}>
                <Chatspert />
              </Elements>
            } />}

It will work

#

Elements will only show after clientSecret is set

blissful quail
#

Just add clientSecret check and your code will work fine