#Srujan

1 messages · Page 1 of 1 (latest)

brittle bloomBOT
opaque perch
#

Hi there

#

Let's start with the first point

mild shale
#

Our backend architecture gives us a new client secret everytime we hit the endpoint, so if the payment amount changes we get a new client secret

opaque perch
#

Are you waiting to mount Payment Element until you have your client secret?

#

Ah I see yeah that's not what you want to do

mild shale
#

I believe so with a true check for clientSecret

opaque perch
#

So when amount changes you should update your PaymentIntent's amount, not create a new one

#

Else you will have to tear-down Payment Element and re-render it

mild shale
#
        <StripeProvider stripe={stripePromise} options={{ clientSecret }}>
          <PaymentsDrawer stripePromise={stripePromise} />
        </StripeProvider>
      )}```
#

Oh I see

#

But this is the check you're asking about right?

opaque perch
#

Instead, you update the PaymentIntent amount from the backend, and call fetchUpdates on the frontend

#

Yes that looks good

mild shale
#

Aha okay so looks like we need a refactor

#

Thanks, I was wondering about that

#

Maybe I'll try to resolve this issue first before going on to the rendering google pay and apple pay, but any tips on that?

#

so I'll want one client secret per payment session, and if I want to update the amount, I have to hit another endpoint to update that client secret, correct?

opaque perch
mild shale
#

Thanks bismarck. How can i save this thread somewhere for my self?

opaque perch
#

I'll archive it but you can still access it

#

And if you have any further questions you can just pop back in the main channel and ask

mild shale
#

Thanks! Appreciate you

#

Wait, before you go...

#

Is the google pay processing identical to what I did using the payment request button or is there something different for processing payment with Payment Element?

#

Like on the payment request button I passed the paymentRequest as options...but here it's auto. Any videos or tutorials I can see of accepting google pay with the Payment Element?

opaque perch
#

It basically just works

#

You don't have to do anything different

mild shale
#

I'm guessing it's just with confirmPayment?

opaque perch
#

You just call confirmPayment

mild shale
#

ah okay sweet

#

Okay, so I still get the options unmutable issue even when I don't change the payment amount, I'm working with one client secret. Is this because of rerenders potentially?

opaque perch
#

Yeah sounds like it

mild shale
opaque perch
#

Yes you won't see it locally

#

(Sorry forgot to mention that)

mild shale
#

But I won't need to call stripe.paymentRequest at all right?

opaque perch
#

Nope

#

You just follow the same steps as with a normal Card Payment

#

(Just render with client-secret and the confirmPayment)

#

If you do update the amount of the PaymentIntent, then it is important you call fetchUpdates client-side, otherwise the wrong amount will be shown in the wallet modal

mild shale
#

okay sounds good

#

How do I pass in layout options into react Payment Element if I'm not using elements.create('payment', {})

#

I'm just importing Payment Element from react-stripe-js

#

Where do I find payment element props?

opaque perch
#

You mean Appearance API?

mild shale
#

Ah yes that's what I was looking for

#

To pass those options, I would have to use elements.create right? Or is there a way to pass options to the PaymentElement directly?

opaque perch
#

You pass options to your Elements provider

#

Something like: <Elements stripe={stripePromise} options={options}> <CheckoutForm /> </Elements>

mild shale
#

ah so when I render the PaymentElement from '@stripe/react-stripe-js' it automatically sends those options?

rocky phoenix
#

You need to configure the options object and provide it -- its optional

#

But if you supply that prop its passed to the elements instance for you, if thats what you mean

mild shale
#

^ yes awesome thanks

#

Still confused how to pass in the client secret and options into the Elements provider

#

like do I define an options object and clientSecret is a property and layout is a property?

#

like ```options = {
clientSecret: clientSecret,
layout: 'accordion'
}

mild shale
#

I'm just trying to figure out how to pass layout: 'accordion' to the payment element easiest. Is i through the options object passed into the provider?

rocky phoenix
mild shale
#

Ok so I see const paymentElement = elements.create('payment', { layout: { type: 'accordion', defaultCollapsed: false, radios: true, spacedAccordionItems: false } });

#

but if I'm just importing PaymentElement from react-stripe-js and using the elements provider, how would I incorporate this? Remove the import and use this
elements = useElements()

#

and then render paymentElement like I would from the import?

rocky phoenix
mild shale
#

Possibly related but not sure, when I run ngrok, I'm getting this Empty total label may be confusing the user

#

which is weird because I'm not creating a payment request

#

I'm also still not able to see google pay. It was working when I first configured the element, but haven't been able to get it to render since then. When I did get it to render, it shows up like it does on the demo https://stripe.com/docs/payments/payment-element, Another step will appear to securely submit your payment information.

#

How do I configure the "another step" to show the google pay interface?

rocky phoenix
#

Ohhh ok. you can do this, but it seems that you need to use the object pattern for the layout options -- that's really not obvious. Or at least I hit errors until I did so.

#
const elementOptions = {
    layout: {
      type:'accordion',
      radios: false,
    },

  };
...
<PaymentElement
        options={elementOptions} />
#

In theory it should be fine to use layout: 'accordion' but that didn't work for me 🤔 (might have been a spearate build issue though)

mild shale
#

I'm getting Type '{ layout: { type: string; }; }' has no properties in common with type 'StripePaymentElementOptions'. as a typeScript error, is there a way to see StripePaymentElementOptions somewhere in the docs?

rocky phoenix
#

hmm i wonder if that wasn't updated? you can tell it to ignore that in case its just the type defs

#

Not in the docs, in the source only

#

Looks like its properly defined

#

oh

#

you know what

#

I've seen an eror like this before

#

do this:

#

const elementOptions: StripePaymentElementOptions = { ... } to force the typing

mild shale
#

ah sweet

rocky phoenix
#

then use it in the payment element

#

its the right shape, it just cant interpret it correctly

mild shale
#
  /**
   * Override the business name displayed in the Payment Element.
   * By default the PaymentElement will use your Stripe account or business name.
   */
  business?: {name: string};

  /**
   * Override the order in which payment methods are displayed in the Payment Element.
   * By default, the Payment Element will use a dynamic ordering that optimizes payment method display for each user.
   */
  paymentMethodOrder?: string[];

  /**
   * Control which fields are displayed in the Payment Element.
   */
  fields?: FieldsOption;

  /**
   * Apply a read-only state to the Payment Element so that payment details can’t be changed.
   * Default is false.
   */
  readOnly?: boolean;

  /**
   * Control terms display in the Payment Element.
   */
  terms?: TermsOption;

  /**
   * Control wallets display in the Payment Element.
   */
  wallets?: WalletsOption;
}```
#

doesn't accept layout I guess 🤷🏾‍♂️

rocky phoenix
#

you must have an old version of @stripe/stripe-js -- try updating that package

mild shale
#

Ah okay

rocky phoenix
#

oh wait

#

that might not be released yet

#

This is after the release of 1.45

mild shale
#

yup I have 1.32.0 so I should update

#

I'll update react as well just to make sure

#

just update react stripe as well, seems stripePromise isn't loading correctly

rocky phoenix
#

That shouldnt have changed

mild shale
#

hmm...did anything change b/t 1.9 and 1.16? 1.16 looks older than 1.9 but it updated to 1.16

#

maybe I should just go back to 1.9?

rocky phoenix
#

The way these work are helpers around Stripe.js, which always loads the latest version

#

So if you can use the version(s) of the package you had, ignore the type error, and get it working with the options, then great!

#

Are there any error raised with the new version of the react-stripe-js with you initialize?

mild shale
#

Oh I just had to restart the app again...weird

#

Okay it's working...now on to the next problem. I can't get google pay to render in my browser. Using chrome, I have payment methods setup, the google pay options is rendering for me on the stripe demo for payment element, but when i click the tab it doesn't open up another window to submit payment details, and it's not showing up locally on my code

#

I'm also getting Unsupported prop change: options.clientSecret is not a mutable property. which must be the issue. I am not rendering the Provider until the clientSecret is defined though and I'm only working with one clientSecret, it might be due to multiple renders though which is my best guess

#

also I'm running ngrok to serve over https

#

looks like the lock icon is showing i have valid ssl

rocky phoenix
#

That should all be fine -- can you show the component logic for the conditional render on clientSecret? I can take a look but my colleague will need to take over shortly.

#

and: great to hear the accordion is working! 🎉

#

🪗

mild shale
#

Yes thanks for your help!

#

ignore the stripePromise being passed to PaymentsDrawer, it isn't being used. I might play around with the StripeProvider placement later but right now it's being passed down because these components were terribly written and have multiple renders

#

PaymentsDrawer component:

import Drawer from '@mui/material/Drawer';
import { styled } from '@mui/material/styles';
import { useCart } from '../../../hooks/useCart';
import { Stripe } from '@stripe/stripe-js';
interface PaymentDrawerProps {
  stripePromise: Promise<Stripe | null> | null;
}

const PaymentDrawer = styled(Drawer)(({ theme }) => ({
  '.MuiDrawer-paperAnchorBottom': {
    height: theme.spacing(105)
  },
  zIndex: 3000
}));

const PaymentsDrawer = ({ stripePromise }: PaymentDrawerProps) => {
  const { openPaymentsDrawer, setOpenPaymentsDrawer, submittingOrderDialog } =
    useCart();
  console.log('how many renders');
  return (
    <PaymentDrawer
      anchor="bottom"
      open={openPaymentsDrawer}
      onClose={() => setOpenPaymentsDrawer(false)}
      hideBackdrop={submittingOrderDialog.open}
      ModalProps={{
        keepMounted: false
      }}
    >
      <PaymentForm stripePromise={stripePromise} />
    </PaymentDrawer>
  );
};

export default PaymentsDrawer;```
#

And finally PaymentForm component:

import { useCart } from '../../../hooks/useCart';
import { useOrder } from '../../../hooks/useOrder';
import { useRestaurant } from '../../../hooks/useRestaurant';
import { Order, OrderStatus } from '../../../types/order';
import { getErrorDialogText } from '../../../utils/Functions/errors';
import { useTranslation } from 'react-i18next';
import { createPostOrderObject } from '../../../utils/Functions/cart';
import { partnerConfig } from '../../../config/appConfig';
import { PostOrder } from '../../../types/fetch';
import { postOrderProcessing } from '../../../utils/Services/backendServices';
import { processOrderProcResponse } from '../../../utils/Functions/data';
import { logEvent } from 'firebase/analytics';
import { useFirebase } from '../../../hooks/useFirebase';
import { useState } from 'react';
import { isRestaurantOpen } from '../../../utils/Functions/restaurant';
import { Stripe, StripePaymentElementOptions } from '@stripe/stripe-js';
import {
  useStripe,
  useElements,
  PaymentElement
} from '@stripe/react-stripe-js';
import { styled } from '@mui/material/styles';

interface PaymentFormProps {
  stripePromise: Promise<Stripe | null> | null;
}

const PaymentElementContainer = styled('div')(({ theme }) => ({
  display: 'flex',
  flexDirection: 'column',
  padding: theme.spacing(6)
}));

const paymentElementOptions: StripePaymentElementOptions = {
  layout: {
    type: 'accordion'
  }
};

const PaymentForm = ({ stripePromise }: PaymentFormProps) => {
  const stripe = useStripe();
  const elements = useElements();
  return (
    <PaymentElementContainer>
      <PaymentElement options={paymentElementOptions} />
    </PaymentElementContainer>
  );
};

export default PaymentForm;```
#

I haven't added in the submit logic yet, but on this video tutorial it seems all the options should show up automatically https://www.youtube.com/watch?v=e-whXipfRvg&t=1s

In this episode, you’ll learn how to accept payments with the Payment Element using React Stripe.js. We’ll also see how to leverage many types of payment methods with one single integration using automatic payment methods.

Presenter

Matthew Ling - Developer Advocate at Stripe - https://twitter.com/mattling_dev

Table of contents

00:00...

▶ Play video
#

One thing to note is even if I don't get the unsupportable prop change, I still don't see google pay in the payment element as an option

#

Sorry to waste time, I believe my backend team didn't push an update for automatic_payment_methods: {enabled: true} so I think that might be the issue

rocky phoenix
#

Yea otherwise everything here looks pretty reasonable -- I'm not spotting any issues that would lead to the failure you described

#

I think revisiting this and breaking things down into smaller steps/chunks to identify the issue, if one exists, is the next step here