#Daniel-paymentintent

1 messages · Page 1 of 1 (latest)

hushed delta
#

Hi!

So you get the intent data on the redirect url after submitting your purchase.
That's correct
Is there any way to handle those smoothlie with react-router(-dom)?
What do you mean by that?

snow jetty
#

Hey!
I´m currently trying to build my "pending page", so the page constantly checking for the payment status update

#
import { useState, useEffect } from 'react';
import { useStripe } from '@stripe/react-stripe-js';
import { PaymentIntentResult } from '@stripe/stripe-js';

const PaymentStatus = () => {
  const stripe = useStripe();
  const [message, setMessage] = useState<String>('');

  useEffect(() => {
    if (!stripe) {
      return;
    }

    // Retrieve the "payment_intent_client_secret" query parameter appended to
    // your return_url by Stripe.js
    const clientSecret = new URLSearchParams(window.location.search).get(
      'payment_intent_client_secret'
    );

    // Retrieve the PaymentIntent
    stripe
      .retrievePaymentIntent(clientSecret!)
      .then(({ paymentIntent }: PaymentIntentResult) => {
        // Inspect the PaymentIntent `status` to indicate the status of the payment
        // to your customer.
        //
        // Some payment methods will [immediately succeed or fail][0] upon
        // confirmation, while others will first enter a `processing` state.
        //
        // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification
        switch (paymentIntent!.status) {
          case 'succeeded':
            setMessage('Success! Payment received.');
            break;

          case 'processing':
            setMessage(
              "Payment processing. We'll update you when payment is received."
            );
            break;

          case 'requires_payment_method':
            // Redirect your user back to your payment page to attempt collecting
            // payment again
            setMessage('Payment failed. Please try another payment method.');
            break;

          default:
            setMessage('Something went wrong.');
            break;
        }
      });
  }, [stripe]);

  return <p>message</p>
};

export default PaymentStatus;
#

thats the payment status component by the official docs

#

problem is, I don´t know how i can render it

#

because now if i try to import it and render it in my index.tsx checkout page, which atm just looks like this:

import PaymentStatus from './PaymentStatus';

const CheckingPayment = () => {
  return (
    <div>
      CheckingPayment
      <PaymentStatus />
    </div>
  );
};

export default CheckingPayment;
#

I get an error telling me that i can only use the useStripe hook when the component is wrapped in an elements component

#

wait, let me check smth

#

okay nvm, I´m kinda lost right here. It tells me like I said I need to useStripe in an Elements provider.
But the elementsprovider is in a way different react component

#

so i need to make a second one?

celest tide
#

hello 👋
taking over here
what's your component hierarchy?

snow jetty
#

I think it works, I just did it like so

#

looks like this in a nutshell, one sec...

#
<Routes>
  <Route "/createOrder" element=... /> <-- In Here is the first Elements provider by Stripe with the loadStripe(key) -> <Elements stripe={stripePromise}></Elements>



  <Route "/pendingPage" element=... /> <-- In Here is the second Elements provider by Stripe, loading the same Promise via loadStripe with the same key again
</Routes>
#

does it make sense?

celest tide
#

ah
so you're trying to render <Elements /> twice?
Is it possible to just nest the component that handles routing in <Elements />?

snow jetty
#

hmmm two questions:
can this have any performance issues?

#

what if I have a second product to sell

#

would that work with one promise?

#

if its all fine i can wrap it around my routes ig

snow jetty
#

it works, but I don´t know if its smart

celest tide
#

Let me take a look

snow jetty
#

sure thanks!

celest tide
#

if its all fine i can wrap it around my routes ig
yup that's would be ideal

snow jetty
#

awesome, thanks alot! Appreciate your quick help on the discord ❤️

celest tide
#

NP! 🙂 Good luck

snow jetty
#

I actually do have another question. So if I want to put it in the root level, I´d have to create the clientSecret on the initial page load, would that be right?

celest tide
#

Yup that's correct

snow jetty
#

Ight

snow jetty
#
v3:1 Uncaught (in promise) IntegrationError: Invalid value for elements(): clientSecret should be a client secret of the form ${id}_secret_${secret}. You specified: .
#

any idea what this error is about?

#
import { FC, useEffect, useState } from 'react';
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import { createPayment } from '../backendRequests/PaymentRequests/createPayment';

const stripePromise = loadStripe(
  'pk_test_51KyzygLkVu8CqnKeoQeb1C6bHnn0axEfI040HfOqdwIirE3CSfbRS385TflBhDug5A2sQminFBDdmqnH5E9By3i200ky6OKWdD'
);

interface StripeAppearance {
  theme: 'stripe' | 'night' | 'flat' | 'none' | undefined;
}

const StripeProvider: FC = ({ children }) => {
  const [clientSecret, setClientSecret] = useState<string>('');

  useEffect(() => {
    // Create PaymentIntent as soon as the page loads
    createPayment(setClientSecret);
  }, []);

  const appearance: StripeAppearance = {
    theme: 'stripe'
  };

  const options = {
    clientSecret,
    appearance
  };
  return (
    <Elements options={options} stripe={stripePromise}>
      {children}
    </Elements>
  );
};

export default StripeProvider;

this is my component pretty much on the root level of my app rn

#

wrapping my Routes component

celest tide
#

can you try printing clientSecret before you pass it into options?

snow jetty
#

you mean before i render the elements object?

celest tide
#

yup

snow jetty
#

I can try

#

dunno if the promise comes back that fast

#

refreshing the page ends in those errors

#

well actually the same lol

#

fixed it

#
  return (
    <>
      {clientSecret ? (
        <Elements options={options} stripe={stripePromise}>
          {children}
        </Elements>
      ) : (
        children
      )}
    </>
  );
#

needed to wait for the clientSecret to be set before rendering <Elements>

celest tide
#

Yup

#

If you check the screenshot, secret is empty 😄 that was the error all about

snow jetty
#

ooh nooo

#

i see

#

well, now this again

#

actually makes no sense rn doesnt it?

celest tide
#

you may want to change this

        <Elements options={options} stripe={stripePromise}>
          {children}
        </Elements>
      ) : (
        children
      )}```

to

clientSecret && ( .... )

snow jetty
#

i think that works

#

yees

celest tide
#

the code that you had is similar to if....else

snow jetty
#

oooh

celest tide
#

so it still renders children without elements if no clientSecret

snow jetty
#

thought it would rerender tho on setstate with the elements provider than

#

but seems not to 😄

celest tide
#

yeah you would get the error on initial render and the code would stop running after that point

snow jetty
#

I see

#

Cool thanks!