#Srujan-react-paymentrequestbutton

1 messages · Page 1 of 1 (latest)

lean spire
#

Hello! We've had people hit this before, but usually they diagnose WHY canMakePayment is called multiple times and correct their code to get rid of the rerenders. Have you pinpointed why your component is being rendered multiple times?

hearty parcel
#

It's because the event handling I am doing makes use of context values that get updated by other components =/.

#

Just confirming though, if I console log I do see multiple console logs within my useEffect that is making the call to canMakePayment (more than 2, I believe React.strictmode runs useEffects twice but this shouldn't affect the display, confirmed from an earlier branch of code where Google Pay was showing up)

#

From the docs: If the checkout flow needs to know whether PaymentRequest.canMakePayment() will return true even before all line items and their prices are known, you can instantiate PaymentRequest with dummy data and pre-query .canMakePayment(). If you call .canMakePayment() multiple times, keep in mind that the first parameter to the PaymentRequest constructor should contain the same method names and data.

#

So I'm wondering if Stripe behind the hood is using the same parameters when making the call?

#

But I think you're right, if I can remove the multiple renders I would be in better shape

#

Sorry I spoke too soon. It does look like my google pay button is only rendering once and the useEffect that makes the canMakePayment call only happens once (twice with strictmode, but again, shouldn't affect the code)

#

I can post my Button here if it helps

lean spire
#

So I'm wondering if Stripe behind the hood is using the same parameters when making the call?
I'm not sure of this since I don't know the specifics of how we've implemented under the hood, but assuming you're creating the Payment Request in useEffect then I'd assume we'd pass the same thing

hearty parcel
#

Would you mind looking at my Google Pay Button component and seeing if you see any reason why it wouldn't be showing? The result coming back from the Promise returned from paymentRequest.canMakePayment is null

#
import { useNavigate } from 'react-router-dom';
import {
  PaymentRequestButtonElement,
  useStripe
} from '@stripe/react-stripe-js';
import { PaymentRequest } from '@stripe/stripe-js';
import fetchClientSecret from '../../../utils/Stripe/fetchClientSecret';
import { getErrorDialogText } from '../../../utils/Functions/errors';
import { useCart } from '../../../hooks/useCart';
import { useOrder } from '../../../hooks/useOrder';
import { useRestaurant } from '../../../hooks/useRestaurant';
import { Order, OrderStatus } from '../../../types/order';

import { useTranslation } from 'react-i18next';

const GooglePayButton = () => {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const stripe = useStripe();
  const cart = useCart();
  const { setOpenOrderModal, orderDispatch } = useOrder();
  const { currentRestaurant } = useRestaurant();

  const {
    stripeAmount,
    userInfo,
    setErrorDialogText,
    setOpenPaymentsDrawer,
    setOpenSubmittingOrderDialog,
    cartDispatch
  } = cart;

  const getTranslatedError = (error: string) => {
    const errorResponse = getErrorDialogText(error);
    setErrorDialogText({
      title: t(errorResponse.title),
      description: t(errorResponse.description)
    });
  };

  const redirectToOrder = () => {
    setOpenOrderModal(true);
    navigate(`/r/${currentRestaurant.restaurantId}`);
  };

  const [paymentRequest, setPaymentRequest] = useState<PaymentRequest>();

  useEffect(() => {
    if (stripe) {
      const pr = stripe.paymentRequest({
        country: 'US',
        currency: 'usd',
        total: {
          label: 'Payment Amount',
          amount: stripeAmount
        }
      });
      // Check the availability of the Payment Request API.
      console.log('how many times does this fucking run');
      pr.canMakePayment()
        .then((result) => {
          if (result) {
            setPaymentRequest(pr);
          }
        })
        .catch((err) => console.error(err));
    }
  }, [stripe, stripeAmount]);

  if (stripe && paymentRequest) {
    paymentRequest.on('paymentmethod', async (ev) => {
      setOpenPaymentsDrawer(false);
      setOpenSubmittingOrderDialog(true);
      const clientSecret = await fetchClientSecret(stripeAmount);
      if (typeof clientSecret === 'string') {
        const { paymentIntent, error } = await stripe.confirmCardPayment(
          clientSecret,
          {
            payment_method: ev.paymentMethod.id,
            receipt_email: userInfo.email
          },
          { handleActions: false }
        );
        if (error && error.code) {
          getTranslatedError(error.code);
          ev.complete('fail');
        }
        ev.complete('success');
        if (paymentIntent && paymentIntent.status === 'requires_action') {
          // Let Stripe.js handle the rest of the payment flow.
          stripe.confirmCardPayment(clientSecret, {
            payment_method: ev.paymentMethod.id,
            receipt_email: userInfo.email
          });
        } else {
          // The payment has succeeded.
          const newOrder: Order = {
            restaurantId: currentRestaurant.restaurantUUID,
            orderNum: 1,
            orderItem: cart,
            orderStatus: OrderStatus.PENDING
          };
          console.log('my new order', newOrder);
          orderDispatch({ type: 'add_order', payload: newOrder });
          window.sessionStorage.removeItem('cart');
          cartDispatch({
            type: 'clear_storage'
          });
          redirectToOrder();
        }
      }
    });
  }
  if (paymentRequest) {
    const options = {
      paymentRequest,
      style: {
        paymentRequestButton: {
          height: '48px',
          borderRadius: '8px'
        }
      }
    };
    return <PaymentRequestButtonElement options={options} />;
  }
  return null;
};

export default GooglePayButton;
lean spire
#

do you actually have a site I can look at instead to start?

hearty parcel
#

Sure

#

The deceptive site ahead warning chrome gives isn't the issue since this is failing on my dev server as well

#

Add an item to the cart and a banner will popup on the bottom and click it, then follow to check out, enter name and phone, then hit continue to pay, and that's where you should see the Button displayed (there's a placeholder text for when it isn't showing)

lean spire
#

Google pay is showing up fine for me - is there supposed to be an error/not show up?

hearty parcel
#

Damn really? Okay...maybe it's just my browser then

lean spire
hearty parcel
#

That one works for me

#

It shows. the error for 2 seconds then displays

#

This shows for a little before the Gpay button shows

#

So weird

lean spire
#

yup, it shows for me there as well (but it does initially show as unavailable and takes one second before showing)

hearty parcel
#

I tried running in incognito mode and signing into my google account but it doesn't show up on the stripe page. Do you know of a good way to test this or browser settings that may be disabling me from seeing it show?

lean spire
#

incognito mode never works with google pay, so that's not an option

hearty parcel
#

ok i got it showing in a new window

#

ty for your help karbi!

lean spire
#

i'm glad it got all sorted out! I know testing the payment request button can be a pain

hearty parcel
#

Well it's not stripe's fault. I believe the source of it is chrome and the payment request api

#

source of pain ***

#

How do you like working for Stripe? Are you technically a dev? Was considering put in an application

#

You probably can't answer truthfully here, that's okay.

lean spire
#

Most of the stripe folks here are devs (including me) 🙂